summaryrefslogtreecommitdiffstats
path: root/cppu
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /cppu
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--cppu/CppunitTest_cppu_any-external.mk25
-rw-r--r--cppu/CppunitTest_cppu_qa_any.mk29
-rw-r--r--cppu/CppunitTest_cppu_qa_recursion.mk27
-rw-r--r--cppu/CppunitTest_cppu_qa_reference.mk29
-rw-r--r--cppu/CppunitTest_cppu_qa_unotype.mk26
-rw-r--r--cppu/CppunitTest_cppu_test_cppumaker.mk29
-rw-r--r--cppu/CppunitTest_cppu_typelib.mk27
-rw-r--r--cppu/InternalUnoApi_cppu_qa_cppumaker_types.mk16
-rw-r--r--cppu/InternalUnoApi_cppu_qa_types.mk16
-rw-r--r--cppu/IwyuFilter_cppu.yaml26
-rw-r--r--cppu/Library_affine_uno_uno.mk24
-rw-r--r--cppu/Library_cppu.mk53
-rw-r--r--cppu/Library_log_uno_uno.mk27
-rw-r--r--cppu/Library_purpenvhelper.mk34
-rw-r--r--cppu/Library_unsafe_uno_uno.mk24
-rw-r--r--cppu/Makefile7
-rw-r--r--cppu/Module_cppu.mk33
-rw-r--r--cppu/README.md8
-rw-r--r--cppu/qa/any-external.cxx63
-rw-r--r--cppu/qa/cppumaker/test_cppumaker.cxx559
-rw-r--r--cppu/qa/cppumaker/types.idl710
-rw-r--r--cppu/qa/test_any.cxx2578
-rw-r--r--cppu/qa/test_recursion.cxx53
-rw-r--r--cppu/qa/test_reference.cxx203
-rw-r--r--cppu/qa/test_unotype.cxx558
-rw-r--r--cppu/qa/typelib.cxx293
-rw-r--r--cppu/qa/types.idl57
-rw-r--r--cppu/source/AffineBridge/AffineBridge.cxx360
-rw-r--r--cppu/source/LogBridge/LogBridge.cxx262
-rw-r--r--cppu/source/UnsafeBridge/UnsafeBridge.cxx144
-rw-r--r--cppu/source/cppu/compat.cxx47
-rw-r--r--cppu/source/cppu/cppu_opt.cxx66
-rw-r--r--cppu/source/helper/purpenv/Proxy.hxx76
-rw-r--r--cppu/source/helper/purpenv/helper_purpenv_Environment.cxx522
-rw-r--r--cppu/source/helper/purpenv/helper_purpenv_Mapping.cxx215
-rw-r--r--cppu/source/helper/purpenv/helper_purpenv_Proxy.cxx504
-rw-r--r--cppu/source/threadpool/current.cxx210
-rw-r--r--cppu/source/threadpool/current.hxx47
-rw-r--r--cppu/source/threadpool/jobqueue.cxx177
-rw-r--r--cppu/source/threadpool/jobqueue.hxx72
-rw-r--r--cppu/source/threadpool/thread.cxx198
-rw-r--r--cppu/source/threadpool/thread.hxx67
-rw-r--r--cppu/source/threadpool/threadident.cxx120
-rw-r--r--cppu/source/threadpool/threadpool.cxx476
-rw-r--r--cppu/source/threadpool/threadpool.hxx162
-rw-r--r--cppu/source/typelib/static_types.cxx555
-rw-r--r--cppu/source/typelib/typelib.cxx2399
-rw-r--r--cppu/source/typelib/typelib.hxx45
-rw-r--r--cppu/source/uno/EnvDcp.cxx43
-rw-r--r--cppu/source/uno/EnvStack.cxx382
-rw-r--r--cppu/source/uno/IdentityMapping.cxx105
-rw-r--r--cppu/source/uno/IdentityMapping.hxx31
-rw-r--r--cppu/source/uno/any.cxx142
-rw-r--r--cppu/source/uno/assign.hxx449
-rw-r--r--cppu/source/uno/cascade_mapping.cxx308
-rw-r--r--cppu/source/uno/cascade_mapping.hxx32
-rw-r--r--cppu/source/uno/check.cxx335
-rw-r--r--cppu/source/uno/constr.hxx138
-rw-r--r--cppu/source/uno/copy.hxx655
-rw-r--r--cppu/source/uno/data.cxx316
-rw-r--r--cppu/source/uno/destr.hxx352
-rw-r--r--cppu/source/uno/eq.hxx635
-rw-r--r--cppu/source/uno/lbenv.cxx1147
-rw-r--r--cppu/source/uno/lbmap.cxx754
-rw-r--r--cppu/source/uno/loadmodule.cxx75
-rw-r--r--cppu/source/uno/loadmodule.hxx47
-rw-r--r--cppu/source/uno/prim.hxx153
-rw-r--r--cppu/source/uno/sequence.cxx912
-rw-r--r--cppu/util/cppu.map158
-rw-r--r--cppu/util/uno_purpenvhelpergcc3.map34
-rw-r--r--cppuhelper/CppunitTest_cppuhelper_cppu_ifcontainer.mk27
-rw-r--r--cppuhelper/CppunitTest_cppuhelper_cppu_unourl.mk23
-rw-r--r--cppuhelper/CppunitTest_cppuhelper_qa_misc.mk27
-rw-r--r--cppuhelper/CppunitTest_cppuhelper_qa_weak.mk27
-rw-r--r--cppuhelper/InternalUnoApi_cppuhelper.mk20
-rw-r--r--cppuhelper/IwyuFilter_cppuhelper.yaml59
-rw-r--r--cppuhelper/Library_cppuhelper.mk75
-rw-r--r--cppuhelper/Makefile14
-rw-r--r--cppuhelper/Module_cppuhelper.mk26
-rw-r--r--cppuhelper/README.md8
-rw-r--r--cppuhelper/StaticLibrary_findsofficepath.mk16
-rw-r--r--cppuhelper/inc/pch/precompiled_cppuhelper.cxx12
-rw-r--r--cppuhelper/inc/pch/precompiled_cppuhelper.hxx111
-rw-r--r--cppuhelper/qa/ifcontainer/cppu_ifcontainer.cxx263
-rw-r--r--cppuhelper/qa/misc/test_misc.cxx91
-rw-r--r--cppuhelper/qa/propertysetmixin/JavaSupplier.java308
-rw-r--r--cppuhelper/qa/propertysetmixin/comp_propertysetmixin.cxx406
-rw-r--r--cppuhelper/qa/propertysetmixin/manifest2
-rw-r--r--cppuhelper/qa/propertysetmixin/qa_propertysetmixin.cpp.component25
-rw-r--r--cppuhelper/qa/propertysetmixin/qa_propertysetmixin.java.component25
-rw-r--r--cppuhelper/qa/propertysetmixin/test_propertysetmixin.cxx639
-rw-r--r--cppuhelper/qa/propertysetmixin/types.idl79
-rw-r--r--cppuhelper/qa/sce/test_unourl.sce1
-rw-r--r--cppuhelper/qa/unourl/cppu_unourl.cxx473
-rw-r--r--cppuhelper/qa/weak/test_weak.cxx99
-rw-r--r--cppuhelper/source/access_control.cxx131
-rw-r--r--cppuhelper/source/bootstrap.cxx242
-rw-r--r--cppuhelper/source/compat.cxx172
-rw-r--r--cppuhelper/source/component.cxx223
-rw-r--r--cppuhelper/source/component_context.cxx590
-rw-r--r--cppuhelper/source/defaultbootstrap.cxx104
-rw-r--r--cppuhelper/source/exc_thrower.cxx314
-rw-r--r--cppuhelper/source/factory.cxx969
-rw-r--r--cppuhelper/source/findsofficepath.c219
-rw-r--r--cppuhelper/source/gcc3.map450
-rw-r--r--cppuhelper/source/implbase.cxx285
-rw-r--r--cppuhelper/source/implbase_ex.cxx402
-rw-r--r--cppuhelper/source/implementationentry.cxx94
-rw-r--r--cppuhelper/source/interfacecontainer.cxx596
-rw-r--r--cppuhelper/source/loadsharedlibcomponentfactory.hxx41
-rw-r--r--cppuhelper/source/macro_expander.cxx171
-rw-r--r--cppuhelper/source/macro_expander.hxx56
-rw-r--r--cppuhelper/source/paths.cxx135
-rw-r--r--cppuhelper/source/paths.hxx40
-rw-r--r--cppuhelper/source/propertysetmixin.cxx1143
-rw-r--r--cppuhelper/source/propshlp.cxx1184
-rw-r--r--cppuhelper/source/servicemanager.cxx2020
-rw-r--r--cppuhelper/source/servicemanager.hxx361
-rw-r--r--cppuhelper/source/shlib.cxx437
-rw-r--r--cppuhelper/source/supportsservice.cxx27
-rw-r--r--cppuhelper/source/tdmgr.cxx660
-rw-r--r--cppuhelper/source/typemanager.cxx2302
-rw-r--r--cppuhelper/source/typemanager.hxx127
-rw-r--r--cppuhelper/source/typeprovider.cxx238
-rw-r--r--cppuhelper/source/unourl.cxx267
-rw-r--r--cppuhelper/source/weak.cxx561
-rw-r--r--cppuhelper/unotypes/cppuhelper/detail/XExceptionThrower.idl41
-rw-r--r--cpputools/Executable_sp2bv.mk26
-rw-r--r--cpputools/Executable_uno.mk33
-rw-r--r--cpputools/Makefile7
-rw-r--r--cpputools/Module_cpputools.mk20
-rw-r--r--cpputools/Package_uno_sh.mk16
-rw-r--r--cpputools/README.md3
-rwxr-xr-xcpputools/scripts/uno.sh47
-rw-r--r--cpputools/source/sp2bv/readme.txt8
-rw-r--r--cpputools/source/sp2bv/sp2bv.cxx122
-rw-r--r--cpputools/source/unoexe/unoexe.cxx543
137 files changed, 37744 insertions, 0 deletions
diff --git a/cppu/CppunitTest_cppu_any-external.mk b/cppu/CppunitTest_cppu_any-external.mk
new file mode 100644
index 000000000..e56b957ea
--- /dev/null
+++ b/cppu/CppunitTest_cppu_any-external.mk
@@ -0,0 +1,25 @@
+# -*- 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,cppu_any-external))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,cppu_any-external, \
+ cppu/qa/any-external \
+))
+
+$(eval $(call gb_CppunitTest_set_external_code,cppu_any-external))
+
+$(eval $(call gb_CppunitTest_use_libraries,cppu_any-external, \
+ cppu \
+ sal \
+))
+
+$(eval $(call gb_CppunitTest_use_udk_api,cppu_any-external))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppu/CppunitTest_cppu_qa_any.mk b/cppu/CppunitTest_cppu_qa_any.mk
new file mode 100644
index 000000000..d565b0fd3
--- /dev/null
+++ b/cppu/CppunitTest_cppu_qa_any.mk
@@ -0,0 +1,29 @@
+# -*- 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,cppu_qa_any))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,cppu_qa_any, \
+ cppu/qa/test_any \
+))
+
+$(eval $(call gb_CppunitTest_use_external,cppu_qa_any,boost_headers))
+
+$(eval $(call gb_CppunitTest_use_libraries,cppu_qa_any, \
+ cppu \
+ sal \
+))
+
+$(eval $(call gb_CppunitTest_use_internal_comprehensive_api,cppu_qa_any, \
+ cppu_qa_types \
+ udkapi \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppu/CppunitTest_cppu_qa_recursion.mk b/cppu/CppunitTest_cppu_qa_recursion.mk
new file mode 100644
index 000000000..9a238fba4
--- /dev/null
+++ b/cppu/CppunitTest_cppu_qa_recursion.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,cppu_qa_recursion))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,cppu_qa_recursion, \
+ cppu/qa/test_recursion \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,cppu_qa_recursion, \
+ cppu \
+ sal \
+))
+
+$(eval $(call gb_CppunitTest_use_internal_comprehensive_api,cppu_qa_recursion, \
+ cppu_qa_types \
+ udkapi \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppu/CppunitTest_cppu_qa_reference.mk b/cppu/CppunitTest_cppu_qa_reference.mk
new file mode 100644
index 000000000..426902b5a
--- /dev/null
+++ b/cppu/CppunitTest_cppu_qa_reference.mk
@@ -0,0 +1,29 @@
+# -*- 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,cppu_qa_reference))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,cppu_qa_reference, \
+ cppu/qa/test_reference \
+))
+
+$(eval $(call gb_CppunitTest_use_external,cppu_qa_reference,boost_headers))
+
+$(eval $(call gb_CppunitTest_use_libraries,cppu_qa_reference, \
+ cppu \
+ sal \
+))
+
+$(eval $(call gb_CppunitTest_use_internal_comprehensive_api,cppu_qa_reference, \
+ cppu_qa_types \
+ udkapi \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppu/CppunitTest_cppu_qa_unotype.mk b/cppu/CppunitTest_cppu_qa_unotype.mk
new file mode 100644
index 000000000..a8eb53aa8
--- /dev/null
+++ b/cppu/CppunitTest_cppu_qa_unotype.mk
@@ -0,0 +1,26 @@
+# -*- 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,cppu_qa_unotype))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,cppu_qa_unotype, \
+ cppu/qa/test_unotype \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,cppu_qa_unotype, \
+ cppu \
+ sal \
+))
+
+$(eval $(call gb_CppunitTest_use_internal_comprehensive_api,cppu_qa_unotype, \
+ udkapi \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppu/CppunitTest_cppu_test_cppumaker.mk b/cppu/CppunitTest_cppu_test_cppumaker.mk
new file mode 100644
index 000000000..c812d94de
--- /dev/null
+++ b/cppu/CppunitTest_cppu_test_cppumaker.mk
@@ -0,0 +1,29 @@
+# -*- 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,cppu_test_cppumaker))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,cppu_test_cppumaker, \
+ cppu/qa/cppumaker/test_cppumaker \
+))
+
+$(eval $(call gb_CppunitTest_use_external,cppu_test_cppumaker,boost_headers))
+
+$(eval $(call gb_CppunitTest_use_libraries,cppu_test_cppumaker, \
+ cppu \
+ sal \
+))
+
+$(eval $(call gb_CppunitTest_use_internal_comprehensive_api,cppu_test_cppumaker, \
+ cppu_qa_cppumaker_types \
+ udkapi \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppu/CppunitTest_cppu_typelib.mk b/cppu/CppunitTest_cppu_typelib.mk
new file mode 100644
index 000000000..ba9236f61
--- /dev/null
+++ b/cppu/CppunitTest_cppu_typelib.mk
@@ -0,0 +1,27 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; 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/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,cppu_typelib))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,cppu_typelib, \
+ cppu/qa/typelib \
+))
+
+$(eval $(call gb_CppunitTest_use_api,cppu_typelib, \
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,cppu_typelib, \
+ cppu \
+ sal \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,cppu_typelib))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppu/InternalUnoApi_cppu_qa_cppumaker_types.mk b/cppu/InternalUnoApi_cppu_qa_cppumaker_types.mk
new file mode 100644
index 000000000..3464bd4ec
--- /dev/null
+++ b/cppu/InternalUnoApi_cppu_qa_cppumaker_types.mk
@@ -0,0 +1,16 @@
+# -*- 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_InternalUnoApi_InternalUnoApi,cppu_qa_cppumaker_types,cppu/qa/cppumaker/types.idl))
+
+$(eval $(call gb_InternalUnoApi_use_api,cppu_qa_cppumaker_types,\
+ udkapi \
+))
+
+# vim:set noet sw=4 ts=4:
diff --git a/cppu/InternalUnoApi_cppu_qa_types.mk b/cppu/InternalUnoApi_cppu_qa_types.mk
new file mode 100644
index 000000000..345722689
--- /dev/null
+++ b/cppu/InternalUnoApi_cppu_qa_types.mk
@@ -0,0 +1,16 @@
+# -*- 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_InternalUnoApi_InternalUnoApi,cppu_qa_types,cppu/qa/types.idl))
+
+$(eval $(call gb_InternalUnoApi_use_api,cppu_qa_types,\
+ udkapi \
+))
+
+# vim:set noet sw=4 ts=4:
diff --git a/cppu/IwyuFilter_cppu.yaml b/cppu/IwyuFilter_cppu.yaml
new file mode 100644
index 000000000..8e9a368b0
--- /dev/null
+++ b/cppu/IwyuFilter_cppu.yaml
@@ -0,0 +1,26 @@
+---
+assumeFilename: cppu/source/uno/data.cxx
+excludelist:
+ cppu/qa/test_any.cxx:
+ # No hpp -> hdl replacement needed
+ - Enum1.hpp
+ - Enum2.hpp
+ - Interface1.hpp
+ - Interface2.hpp
+ - Interface2a.hpp
+ - Interface2b.hpp
+ - Interface3.hpp
+ cppu/source/cppu/cppu_opt.cxx:
+ # Unit test fails without uno/Any.hxx
+ - com/sun/star/uno/Any.hxx
+ cppu/source/helper/purpenv/helper_purpenv_Environment.cxx:
+ # Needed by the implementation of Environment_initWithEnterable
+ - cppu/helper/purpenv/Environment.hxx
+ cppu/source/threadpool/current.cxx:
+ # FIXME removing this makes linking fail in binaryurp
+ - uno/current_context.h
+ cppu/source/threadpool/threadident.cxx:
+ # Don't replace hxx -> h in URE API
+ - rtl/byteseq.hxx
+ # FIXME removing this makes linking fail in binaryurp
+ - uno/threadpool.h
diff --git a/cppu/Library_affine_uno_uno.mk b/cppu/Library_affine_uno_uno.mk
new file mode 100644
index 000000000..10b5389b5
--- /dev/null
+++ b/cppu/Library_affine_uno_uno.mk
@@ -0,0 +1,24 @@
+# -*- 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_Library_Library,affine_uno_uno))
+
+$(eval $(call gb_Library_use_udk_api,affine_uno_uno))
+
+$(eval $(call gb_Library_use_libraries,affine_uno_uno,\
+ purpenvhelper \
+ sal \
+))
+
+$(eval $(call gb_Library_add_exception_objects,affine_uno_uno,\
+ cppu/source/AffineBridge/AffineBridge \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppu/Library_cppu.mk b/cppu/Library_cppu.mk
new file mode 100644
index 000000000..d1874822b
--- /dev/null
+++ b/cppu/Library_cppu.mk
@@ -0,0 +1,53 @@
+# -*- 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_Library_Library,cppu))
+
+$(eval $(call gb_Library_set_soversion_script,cppu,$(SRCDIR)/cppu/util/cppu.map))
+
+$(eval $(call gb_Library_use_udk_api,cppu))
+
+$(eval $(call gb_Library_set_is_ure_library_or_dependency,cppu))
+
+$(eval $(call gb_Library_add_defs,cppu,\
+ -DCPPU_DLLIMPLEMENTATION \
+))
+
+$(eval $(call gb_Library_use_external,cppu,boost_headers))
+
+$(eval $(call gb_Library_use_libraries,cppu,\
+ sal \
+ salhelper \
+))
+
+$(eval $(call gb_Library_add_exception_objects,cppu,\
+ cppu/source/cppu/compat \
+ cppu/source/cppu/cppu_opt \
+ cppu/source/threadpool/current \
+ cppu/source/threadpool/jobqueue \
+ cppu/source/threadpool/thread \
+ cppu/source/threadpool/threadident \
+ cppu/source/threadpool/threadpool \
+ cppu/source/typelib/static_types \
+ cppu/source/typelib/typelib \
+ cppu/source/uno/any \
+ cppu/source/uno/cascade_mapping \
+ cppu/source/uno/check \
+ cppu/source/uno/data \
+ cppu/source/uno/EnvDcp \
+ cppu/source/uno/EnvStack \
+ cppu/source/uno/IdentityMapping \
+ cppu/source/uno/lbenv \
+ cppu/source/uno/lbmap \
+ cppu/source/uno/loadmodule \
+ cppu/source/uno/sequence \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppu/Library_log_uno_uno.mk b/cppu/Library_log_uno_uno.mk
new file mode 100644
index 000000000..92d287ea7
--- /dev/null
+++ b/cppu/Library_log_uno_uno.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_Library_Library,log_uno_uno))
+
+$(eval $(call gb_Library_use_external,log_uno_uno,boost_headers))
+
+$(eval $(call gb_Library_use_udk_api,log_uno_uno))
+
+$(eval $(call gb_Library_use_libraries,log_uno_uno,\
+ cppu \
+ purpenvhelper \
+ sal \
+))
+
+$(eval $(call gb_Library_add_exception_objects,log_uno_uno,\
+ cppu/source/LogBridge/LogBridge \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppu/Library_purpenvhelper.mk b/cppu/Library_purpenvhelper.mk
new file mode 100644
index 000000000..9aca5818a
--- /dev/null
+++ b/cppu/Library_purpenvhelper.mk
@@ -0,0 +1,34 @@
+# -*- 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_Library_Library,purpenvhelper))
+
+$(eval $(call gb_Library_set_soversion_script,purpenvhelper,$(SRCDIR)/cppu/util/uno_purpenvhelpergcc3.map))
+
+$(eval $(call gb_Library_add_defs,purpenvhelper,\
+ -DPURPENV_DLLIMPLEMENTATION \
+))
+
+$(eval $(call gb_Library_set_is_ure_library_or_dependency,purpenvhelper))
+
+$(eval $(call gb_Library_use_udk_api,purpenvhelper))
+
+$(eval $(call gb_Library_use_libraries,purpenvhelper,\
+ cppu \
+ sal \
+))
+
+$(eval $(call gb_Library_add_exception_objects,purpenvhelper,\
+ cppu/source/helper/purpenv/helper_purpenv_Environment \
+ cppu/source/helper/purpenv/helper_purpenv_Mapping \
+ cppu/source/helper/purpenv/helper_purpenv_Proxy \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppu/Library_unsafe_uno_uno.mk b/cppu/Library_unsafe_uno_uno.mk
new file mode 100644
index 000000000..9733f7216
--- /dev/null
+++ b/cppu/Library_unsafe_uno_uno.mk
@@ -0,0 +1,24 @@
+# -*- 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_Library_Library,unsafe_uno_uno))
+
+$(eval $(call gb_Library_use_udk_api,unsafe_uno_uno))
+
+$(eval $(call gb_Library_use_libraries,unsafe_uno_uno,\
+ purpenvhelper \
+ sal \
+))
+
+$(eval $(call gb_Library_add_exception_objects,unsafe_uno_uno,\
+ cppu/source/UnsafeBridge/UnsafeBridge \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppu/Makefile b/cppu/Makefile
new file mode 100644
index 000000000..ccb1c85a0
--- /dev/null
+++ b/cppu/Makefile
@@ -0,0 +1,7 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+
+module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
+
+include $(module_directory)/../solenv/gbuild/partial_build.mk
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppu/Module_cppu.mk b/cppu/Module_cppu.mk
new file mode 100644
index 000000000..17f6936f7
--- /dev/null
+++ b/cppu/Module_cppu.mk
@@ -0,0 +1,33 @@
+# -*- 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_Module_Module,cppu))
+
+$(eval $(call gb_Module_add_targets,cppu,\
+ InternalUnoApi_cppu_qa_cppumaker_types \
+ InternalUnoApi_cppu_qa_types \
+ Library_affine_uno_uno \
+ Library_cppu \
+ Library_log_uno_uno \
+ Library_purpenvhelper \
+ Library_unsafe_uno_uno \
+))
+
+$(eval $(call gb_Module_add_check_targets,cppu,\
+ CppunitTest_cppu_any-external \
+ CppunitTest_cppu_qa_any \
+ CppunitTest_cppu_qa_recursion \
+ CppunitTest_cppu_qa_reference \
+ CppunitTest_cppu_qa_unotype \
+ CppunitTest_cppu_test_cppumaker \
+ CppunitTest_cppu_typelib \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppu/README.md b/cppu/README.md
new file mode 100644
index 000000000..3249d15e6
--- /dev/null
+++ b/cppu/README.md
@@ -0,0 +1,8 @@
+# Binary UNO Runtime
+
+CPPU stands for C++ UNO and it contains type definitions / implementations for the core of UNO. The
+exported API is in C, and there exists some C++ wrappers.
+
+## See also
+
+<http://wiki.openoffice.org/wiki/Uno/Binary/Modules/CPPU>
diff --git a/cppu/qa/any-external.cxx b/cppu/qa/any-external.cxx
new file mode 100644
index 000000000..bac613427
--- /dev/null
+++ b/cppu/qa/any-external.cxx
@@ -0,0 +1,63 @@
+/* -*- 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 <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <com/sun/star/uno/Any.hxx>
+#include <sal/types.h>
+
+namespace {
+
+class Test: public CppUnit::TestFixture {
+private:
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testGet);
+ CPPUNIT_TEST(testHas);
+ CPPUNIT_TEST(testExtract);
+ CPPUNIT_TEST(testInsert);
+ CPPUNIT_TEST_SUITE_END();
+
+ void testGet() {
+ css::uno::Any a(false);
+ CPPUNIT_ASSERT_EQUAL(a, a.get<css::uno::Any>());
+ CPPUNIT_ASSERT_EQUAL(false, a.get<bool>());
+ }
+
+ void testHas() {
+ css::uno::Any a(false);
+ CPPUNIT_ASSERT_EQUAL(true, a.has<css::uno::Any>());
+ CPPUNIT_ASSERT_EQUAL(true, a.has<bool>());
+ }
+
+ void testExtract() {
+ css::uno::Any a1(false);
+ css::uno::Any a2;
+ CPPUNIT_ASSERT(a1 >>= a2);
+ CPPUNIT_ASSERT_EQUAL(a1, a2);
+ }
+
+ void testInsert() {
+ css::uno::Any a;
+ a <<= css::uno::Any(false);
+ CPPUNIT_ASSERT_EQUAL(css::uno::Any(false), a);
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/cppu/qa/cppumaker/test_cppumaker.cxx b/cppu/qa/cppumaker/test_cppumaker.cxx
new file mode 100644
index 000000000..a6d3e4942
--- /dev/null
+++ b/cppu/qa/cppumaker/test_cppumaker.cxx
@@ -0,0 +1,559 @@
+/* -*- 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 <FILE.hpp>
+#include <lconv.hpp>
+#include <tm.hpp>
+#include <std.hpp>
+#include <test/codemaker/cppumaker/XTest.hpp>
+#include <test/codemaker/cppumaker/S1.hpp>
+#include <test/codemaker/cppumaker/services/asm.hpp>
+#include <test/codemaker/cppumaker/services/auto.hpp>
+#include <test/codemaker/cppumaker/services/bool.hpp>
+#include <test/codemaker/cppumaker/services/break.hpp>
+//TODO: #include "test/codemaker/cppumaker/services/case.hpp"
+#include <test/codemaker/cppumaker/services/catch.hpp>
+//TODO: #include "test/codemaker/cppumaker/services/char.hpp"
+#include <test/codemaker/cppumaker/services/class.hpp>
+//TODO: #include "test/codemaker/cppumaker/services/const.hpp"
+#include <test/codemaker/cppumaker/services/continue.hpp>
+//TODO: #include "test/codemaker/cppumaker/services/default.hpp"
+#include <test/codemaker/cppumaker/services/delete.hpp>
+#include <test/codemaker/cppumaker/services/do.hpp>
+//TODO: #include "test/codemaker/cppumaker/services/double.hpp"
+#include <test/codemaker/cppumaker/services/else.hpp>
+//TODO: #include "test/codemaker/cppumaker/services/enum.hpp"
+#include <test/codemaker/cppumaker/services/explicit.hpp>
+#include <test/codemaker/cppumaker/services/export.hpp>
+#include <test/codemaker/cppumaker/services/extern.hpp>
+#include <test/codemaker/cppumaker/services/false.hpp>
+//TODO: #include "test/codemaker/cppumaker/services/float.hpp"
+#include <test/codemaker/cppumaker/services/for.hpp>
+#include <test/codemaker/cppumaker/services/friend.hpp>
+#include <test/codemaker/cppumaker/services/goto.hpp>
+#include <test/codemaker/cppumaker/services/if.hpp>
+#include <test/codemaker/cppumaker/services/inline.hpp>
+#include <test/codemaker/cppumaker/services/int.hpp>
+//TODO: #include "test/codemaker/cppumaker/services/long.hpp"
+#include <test/codemaker/cppumaker/services/mutable.hpp>
+#include <test/codemaker/cppumaker/services/namespace.hpp>
+#include <test/codemaker/cppumaker/services/new.hpp>
+#include <test/codemaker/cppumaker/services/operator.hpp>
+#include <test/codemaker/cppumaker/services/private.hpp>
+#include <test/codemaker/cppumaker/services/protected.hpp>
+#include <test/codemaker/cppumaker/services/public.hpp>
+#include <test/codemaker/cppumaker/services/register.hpp>
+#include <test/codemaker/cppumaker/services/return.hpp>
+//TODO: #include "test/codemaker/cppumaker/services/short.hpp"
+#include <test/codemaker/cppumaker/services/signed.hpp>
+#include <test/codemaker/cppumaker/services/sizeof.hpp>
+#include <test/codemaker/cppumaker/services/static.hpp>
+//TODO: #include "test/codemaker/cppumaker/services/struct.hpp"
+//TODO: #include "test/codemaker/cppumaker/services/switch.hpp"
+#include <test/codemaker/cppumaker/services/template.hpp>
+#include <test/codemaker/cppumaker/services/this.hpp>
+#include <test/codemaker/cppumaker/services/throw.hpp>
+#include <test/codemaker/cppumaker/services/true.hpp>
+#include <test/codemaker/cppumaker/services/try.hpp>
+//TODO: #include "test/codemaker/cppumaker/services/typedef.hpp"
+#include <test/codemaker/cppumaker/services/typeid.hpp>
+#include <test/codemaker/cppumaker/services/typename.hpp>
+//TODO: #include "test/codemaker/cppumaker/services/union.hpp"
+//TODO: #include "test/codemaker/cppumaker/services/unsigned.hpp"
+#include <test/codemaker/cppumaker/services/using.hpp>
+#include <test/codemaker/cppumaker/services/virtual.hpp>
+//TODO: #include "test/codemaker/cppumaker/services/void.hpp"
+#include <test/codemaker/cppumaker/services/volatile.hpp>
+#include <test/codemaker/cppumaker/services/while.hpp>
+#include <test/codemaker/cppumaker/services/and.hpp>
+#include <test/codemaker/cppumaker/services/bitand.hpp>
+#include <test/codemaker/cppumaker/services/bitor.hpp>
+#include <test/codemaker/cppumaker/services/compl.hpp>
+#include <test/codemaker/cppumaker/services/not.hpp>
+#include <test/codemaker/cppumaker/services/or.hpp>
+#include <test/codemaker/cppumaker/services/xor.hpp>
+#include <test/codemaker/cppumaker/services/BUFSIZ.hpp>
+#include <test/codemaker/cppumaker/services/CLOCKS_PER_SEC.hpp>
+#include <test/codemaker/cppumaker/services/EDOM.hpp>
+#include <test/codemaker/cppumaker/services/EOF.hpp>
+#include <test/codemaker/cppumaker/services/ERANGE.hpp>
+#include <test/codemaker/cppumaker/services/EXIT_FAILURE.hpp>
+#include <test/codemaker/cppumaker/services/EXIT_SUCCESS.hpp>
+#include <test/codemaker/cppumaker/services/FILENAME_MAX.hpp>
+#include <test/codemaker/cppumaker/services/FOPEN_MAX.hpp>
+#include <test/codemaker/cppumaker/services/HUGE_VAL.hpp>
+#include <test/codemaker/cppumaker/services/LC_ALL.hpp>
+#include <test/codemaker/cppumaker/services/LC_COLLATE.hpp>
+#include <test/codemaker/cppumaker/services/LC_CTYPE.hpp>
+#include <test/codemaker/cppumaker/services/LC_MONETARY.hpp>
+#include <test/codemaker/cppumaker/services/LC_NUMERIC.hpp>
+#include <test/codemaker/cppumaker/services/LC_TIME.hpp>
+#include <test/codemaker/cppumaker/services/L_tmpnam.hpp>
+#include <test/codemaker/cppumaker/services/MB_CUR_MAX.hpp>
+#include <test/codemaker/cppumaker/services/NULL.hpp>
+#include <test/codemaker/cppumaker/services/RAND_MAX.hpp>
+#include <test/codemaker/cppumaker/services/SEEK_CUR.hpp>
+#include <test/codemaker/cppumaker/services/SEEK_END.hpp>
+#include <test/codemaker/cppumaker/services/SEEK_SET.hpp>
+#include <test/codemaker/cppumaker/services/SIGABRT.hpp>
+#include <test/codemaker/cppumaker/services/SIGFPE.hpp>
+#include <test/codemaker/cppumaker/services/SIGILL.hpp>
+#include <test/codemaker/cppumaker/services/SIGINT.hpp>
+#include <test/codemaker/cppumaker/services/SIGSEGV.hpp>
+#include <test/codemaker/cppumaker/services/SIGTERM.hpp>
+#include <test/codemaker/cppumaker/services/SIG_DFL.hpp>
+#include <test/codemaker/cppumaker/services/SIG_ERR.hpp>
+#include <test/codemaker/cppumaker/services/SIG_IGN.hpp>
+#include <test/codemaker/cppumaker/services/TMP_MAX.hpp>
+#include <test/codemaker/cppumaker/services/WCHAR_MAX.hpp>
+#include <test/codemaker/cppumaker/services/WCHAR_MIN.hpp>
+#include <test/codemaker/cppumaker/services/WEOF.hpp>
+#include <test/codemaker/cppumaker/services/assert.hpp>
+#include <test/codemaker/cppumaker/services/errno.hpp>
+#include <test/codemaker/cppumaker/services/offsetof.hpp>
+#include <test/codemaker/cppumaker/services/setjmp.hpp>
+#include <test/codemaker/cppumaker/services/stderr.hpp>
+#include <test/codemaker/cppumaker/services/stdin.hpp>
+#include <test/codemaker/cppumaker/services/stdout.hpp>
+#include <test/codemaker/cppumaker/services/CHAR_BIT.hpp>
+#include <test/codemaker/cppumaker/services/CHAR_MAX.hpp>
+#include <test/codemaker/cppumaker/services/CHAR_MIN.hpp>
+#include <test/codemaker/cppumaker/services/DBL_DIG.hpp>
+#include <test/codemaker/cppumaker/services/DBL_EPSILON.hpp>
+#include <test/codemaker/cppumaker/services/DBL_MANT_DIG.hpp>
+#include <test/codemaker/cppumaker/services/DBL_MAX.hpp>
+#include <test/codemaker/cppumaker/services/DBL_MAX_10_EXP.hpp>
+#include <test/codemaker/cppumaker/services/DBL_MAX_EXP.hpp>
+#include <test/codemaker/cppumaker/services/DBL_MIN.hpp>
+#include <test/codemaker/cppumaker/services/DBL_MIN_10_EXP.hpp>
+#include <test/codemaker/cppumaker/services/DBL_MIN_EXP.hpp>
+#include <test/codemaker/cppumaker/services/FLT_DIG.hpp>
+#include <test/codemaker/cppumaker/services/FLT_EPSILON.hpp>
+#include <test/codemaker/cppumaker/services/FLT_MANT_DIG.hpp>
+#include <test/codemaker/cppumaker/services/FLT_MAX.hpp>
+#include <test/codemaker/cppumaker/services/FLT_MAX_10_EXP.hpp>
+#include <test/codemaker/cppumaker/services/FLT_MAX_EXP.hpp>
+#include <test/codemaker/cppumaker/services/FLT_MIN.hpp>
+#include <test/codemaker/cppumaker/services/FLT_MIN_10_EXP.hpp>
+#include <test/codemaker/cppumaker/services/FLT_MIN_EXP.hpp>
+#include <test/codemaker/cppumaker/services/FLT_RADIX.hpp>
+#include <test/codemaker/cppumaker/services/FLT_ROUNDS.hpp>
+#include <test/codemaker/cppumaker/services/INT_MAX.hpp>
+#include <test/codemaker/cppumaker/services/INT_MIN.hpp>
+#include <test/codemaker/cppumaker/services/LDBL_DIG.hpp>
+#include <test/codemaker/cppumaker/services/LDBL_EPSILON.hpp>
+#include <test/codemaker/cppumaker/services/LDBL_MANT_DIG.hpp>
+#include <test/codemaker/cppumaker/services/LDBL_MAX.hpp>
+#include <test/codemaker/cppumaker/services/LDBL_MAX_10_EXP.hpp>
+#include <test/codemaker/cppumaker/services/LDBL_MAX_EXP.hpp>
+#include <test/codemaker/cppumaker/services/LDBL_MIN.hpp>
+#include <test/codemaker/cppumaker/services/LDBL_MIN_10_EXP.hpp>
+#include <test/codemaker/cppumaker/services/LDBL_MIN_EXP.hpp>
+#include <test/codemaker/cppumaker/services/LONG_MAX.hpp>
+#include <test/codemaker/cppumaker/services/LONG_MIN.hpp>
+#include <test/codemaker/cppumaker/services/MB_LEN_MAX.hpp>
+#include <test/codemaker/cppumaker/services/SCHAR_MAX.hpp>
+#include <test/codemaker/cppumaker/services/SCHAR_MIN.hpp>
+#include <test/codemaker/cppumaker/services/SHRT_MAX.hpp>
+#include <test/codemaker/cppumaker/services/SHRT_MIN.hpp>
+#include <test/codemaker/cppumaker/services/UCHAR_MAX.hpp>
+#include <test/codemaker/cppumaker/services/UINT_MAX.hpp>
+#include <test/codemaker/cppumaker/services/ULONG_MAX.hpp>
+#include <test/codemaker/cppumaker/services/USHRT_MAX.hpp>
+#include <test/codemaker/cppumaker/services/FILE.hpp>
+#include <test/codemaker/cppumaker/services/lconv.hpp>
+#include <test/codemaker/cppumaker/services/tm.hpp>
+#include <test/codemaker/cppumaker/services/std.hpp>
+#include <test/codemaker/cppumaker/services/NDEBUG.hpp>
+#include <test/codemaker/cppumaker/services/create.hpp>
+#include <test/codemaker/cppumaker/singletons/asm.hpp>
+#include <test/codemaker/cppumaker/singletons/auto.hpp>
+#include <test/codemaker/cppumaker/singletons/bool.hpp>
+#include <test/codemaker/cppumaker/singletons/break.hpp>
+//TODO: #include "test/codemaker/cppumaker/singletons/case.hpp"
+#include <test/codemaker/cppumaker/singletons/catch.hpp>
+//TODO: #include "test/codemaker/cppumaker/singletons/char.hpp"
+#include <test/codemaker/cppumaker/singletons/class.hpp>
+//TODO: #include "test/codemaker/cppumaker/singletons/const.hpp"
+#include <test/codemaker/cppumaker/singletons/continue.hpp>
+//TODO: #include "test/codemaker/cppumaker/singletons/default.hpp"
+#include <test/codemaker/cppumaker/singletons/delete.hpp>
+#include <test/codemaker/cppumaker/singletons/do.hpp>
+//TODO: #include "test/codemaker/cppumaker/singletons/double.hpp"
+#include <test/codemaker/cppumaker/singletons/else.hpp>
+//TODO: #include "test/codemaker/cppumaker/singletons/enum.hpp"
+#include <test/codemaker/cppumaker/singletons/explicit.hpp>
+#include <test/codemaker/cppumaker/singletons/export.hpp>
+#include <test/codemaker/cppumaker/singletons/extern.hpp>
+#include <test/codemaker/cppumaker/singletons/false.hpp>
+//TODO: #include "test/codemaker/cppumaker/singletons/float.hpp"
+#include <test/codemaker/cppumaker/singletons/for.hpp>
+#include <test/codemaker/cppumaker/singletons/friend.hpp>
+#include <test/codemaker/cppumaker/singletons/goto.hpp>
+#include <test/codemaker/cppumaker/singletons/if.hpp>
+#include <test/codemaker/cppumaker/singletons/inline.hpp>
+#include <test/codemaker/cppumaker/singletons/int.hpp>
+//TODO: #include "test/codemaker/cppumaker/singletons/long.hpp"
+#include <test/codemaker/cppumaker/singletons/mutable.hpp>
+#include <test/codemaker/cppumaker/singletons/namespace.hpp>
+#include <test/codemaker/cppumaker/singletons/new.hpp>
+#include <test/codemaker/cppumaker/singletons/operator.hpp>
+#include <test/codemaker/cppumaker/singletons/private.hpp>
+#include <test/codemaker/cppumaker/singletons/protected.hpp>
+#include <test/codemaker/cppumaker/singletons/public.hpp>
+#include <test/codemaker/cppumaker/singletons/register.hpp>
+#include <test/codemaker/cppumaker/singletons/return.hpp>
+//TODO: #include "test/codemaker/cppumaker/singletons/short.hpp"
+#include <test/codemaker/cppumaker/singletons/signed.hpp>
+#include <test/codemaker/cppumaker/singletons/sizeof.hpp>
+#include <test/codemaker/cppumaker/singletons/static.hpp>
+//TODO: #include "test/codemaker/cppumaker/singletons/struct.hpp"
+//TODO: #include "test/codemaker/cppumaker/singletons/switch.hpp"
+#include <test/codemaker/cppumaker/singletons/template.hpp>
+#include <test/codemaker/cppumaker/singletons/this.hpp>
+#include <test/codemaker/cppumaker/singletons/throw.hpp>
+#include <test/codemaker/cppumaker/singletons/true.hpp>
+#include <test/codemaker/cppumaker/singletons/try.hpp>
+//TODO: #include "test/codemaker/cppumaker/singletons/typedef.hpp"
+#include <test/codemaker/cppumaker/singletons/typeid.hpp>
+#include <test/codemaker/cppumaker/singletons/typename.hpp>
+//TODO: #include "test/codemaker/cppumaker/singletons/union.hpp"
+//TODO: #include "test/codemaker/cppumaker/singletons/unsigned.hpp"
+#include <test/codemaker/cppumaker/singletons/using.hpp>
+#include <test/codemaker/cppumaker/singletons/virtual.hpp>
+//TODO: #include "test/codemaker/cppumaker/singletons/void.hpp"
+#include <test/codemaker/cppumaker/singletons/volatile.hpp>
+#include <test/codemaker/cppumaker/singletons/while.hpp>
+#include <test/codemaker/cppumaker/singletons/and.hpp>
+#include <test/codemaker/cppumaker/singletons/bitand.hpp>
+#include <test/codemaker/cppumaker/singletons/bitor.hpp>
+#include <test/codemaker/cppumaker/singletons/compl.hpp>
+#include <test/codemaker/cppumaker/singletons/not.hpp>
+#include <test/codemaker/cppumaker/singletons/or.hpp>
+#include <test/codemaker/cppumaker/singletons/xor.hpp>
+#include <test/codemaker/cppumaker/singletons/BUFSIZ.hpp>
+#include <test/codemaker/cppumaker/singletons/CLOCKS_PER_SEC.hpp>
+#include <test/codemaker/cppumaker/singletons/EDOM.hpp>
+#include <test/codemaker/cppumaker/singletons/EOF.hpp>
+#include <test/codemaker/cppumaker/singletons/ERANGE.hpp>
+#include <test/codemaker/cppumaker/singletons/EXIT_FAILURE.hpp>
+#include <test/codemaker/cppumaker/singletons/EXIT_SUCCESS.hpp>
+#include <test/codemaker/cppumaker/singletons/FILENAME_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/FOPEN_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/HUGE_VAL.hpp>
+#include <test/codemaker/cppumaker/singletons/LC_ALL.hpp>
+#include <test/codemaker/cppumaker/singletons/LC_COLLATE.hpp>
+#include <test/codemaker/cppumaker/singletons/LC_CTYPE.hpp>
+#include <test/codemaker/cppumaker/singletons/LC_MONETARY.hpp>
+#include <test/codemaker/cppumaker/singletons/LC_NUMERIC.hpp>
+#include <test/codemaker/cppumaker/singletons/LC_TIME.hpp>
+#include <test/codemaker/cppumaker/singletons/L_tmpnam.hpp>
+#include <test/codemaker/cppumaker/singletons/MB_CUR_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/NULL.hpp>
+#include <test/codemaker/cppumaker/singletons/RAND_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/SEEK_CUR.hpp>
+#include <test/codemaker/cppumaker/singletons/SEEK_END.hpp>
+#include <test/codemaker/cppumaker/singletons/SEEK_SET.hpp>
+#include <test/codemaker/cppumaker/singletons/SIGABRT.hpp>
+#include <test/codemaker/cppumaker/singletons/SIGFPE.hpp>
+#include <test/codemaker/cppumaker/singletons/SIGILL.hpp>
+#include <test/codemaker/cppumaker/singletons/SIGINT.hpp>
+#include <test/codemaker/cppumaker/singletons/SIGSEGV.hpp>
+#include <test/codemaker/cppumaker/singletons/SIGTERM.hpp>
+#include <test/codemaker/cppumaker/singletons/SIG_DFL.hpp>
+#include <test/codemaker/cppumaker/singletons/SIG_ERR.hpp>
+#include <test/codemaker/cppumaker/singletons/SIG_IGN.hpp>
+#include <test/codemaker/cppumaker/singletons/TMP_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/WCHAR_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/WCHAR_MIN.hpp>
+#include <test/codemaker/cppumaker/singletons/WEOF.hpp>
+#include <test/codemaker/cppumaker/singletons/assert.hpp>
+#include <test/codemaker/cppumaker/singletons/errno.hpp>
+#include <test/codemaker/cppumaker/singletons/offsetof.hpp>
+#include <test/codemaker/cppumaker/singletons/setjmp.hpp>
+#include <test/codemaker/cppumaker/singletons/stderr.hpp>
+#include <test/codemaker/cppumaker/singletons/stdin.hpp>
+#include <test/codemaker/cppumaker/singletons/stdout.hpp>
+#include <test/codemaker/cppumaker/singletons/CHAR_BIT.hpp>
+#include <test/codemaker/cppumaker/singletons/CHAR_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/CHAR_MIN.hpp>
+#include <test/codemaker/cppumaker/singletons/DBL_DIG.hpp>
+#include <test/codemaker/cppumaker/singletons/DBL_EPSILON.hpp>
+#include <test/codemaker/cppumaker/singletons/DBL_MANT_DIG.hpp>
+#include <test/codemaker/cppumaker/singletons/DBL_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/DBL_MAX_10_EXP.hpp>
+#include <test/codemaker/cppumaker/singletons/DBL_MAX_EXP.hpp>
+#include <test/codemaker/cppumaker/singletons/DBL_MIN.hpp>
+#include <test/codemaker/cppumaker/singletons/DBL_MIN_10_EXP.hpp>
+#include <test/codemaker/cppumaker/singletons/DBL_MIN_EXP.hpp>
+#include <test/codemaker/cppumaker/singletons/FLT_DIG.hpp>
+#include <test/codemaker/cppumaker/singletons/FLT_EPSILON.hpp>
+#include <test/codemaker/cppumaker/singletons/FLT_MANT_DIG.hpp>
+#include <test/codemaker/cppumaker/singletons/FLT_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/FLT_MAX_10_EXP.hpp>
+#include <test/codemaker/cppumaker/singletons/FLT_MAX_EXP.hpp>
+#include <test/codemaker/cppumaker/singletons/FLT_MIN.hpp>
+#include <test/codemaker/cppumaker/singletons/FLT_MIN_10_EXP.hpp>
+#include <test/codemaker/cppumaker/singletons/FLT_MIN_EXP.hpp>
+#include <test/codemaker/cppumaker/singletons/FLT_RADIX.hpp>
+#include <test/codemaker/cppumaker/singletons/FLT_ROUNDS.hpp>
+#include <test/codemaker/cppumaker/singletons/INT_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/INT_MIN.hpp>
+#include <test/codemaker/cppumaker/singletons/LDBL_DIG.hpp>
+#include <test/codemaker/cppumaker/singletons/LDBL_EPSILON.hpp>
+#include <test/codemaker/cppumaker/singletons/LDBL_MANT_DIG.hpp>
+#include <test/codemaker/cppumaker/singletons/LDBL_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/LDBL_MAX_10_EXP.hpp>
+#include <test/codemaker/cppumaker/singletons/LDBL_MAX_EXP.hpp>
+#include <test/codemaker/cppumaker/singletons/LDBL_MIN.hpp>
+#include <test/codemaker/cppumaker/singletons/LDBL_MIN_10_EXP.hpp>
+#include <test/codemaker/cppumaker/singletons/LDBL_MIN_EXP.hpp>
+#include <test/codemaker/cppumaker/singletons/LONG_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/LONG_MIN.hpp>
+#include <test/codemaker/cppumaker/singletons/MB_LEN_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/SCHAR_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/SCHAR_MIN.hpp>
+#include <test/codemaker/cppumaker/singletons/SHRT_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/SHRT_MIN.hpp>
+#include <test/codemaker/cppumaker/singletons/UCHAR_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/UINT_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/ULONG_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/USHRT_MAX.hpp>
+#include <test/codemaker/cppumaker/singletons/FILE.hpp>
+#include <test/codemaker/cppumaker/singletons/lconv.hpp>
+#include <test/codemaker/cppumaker/singletons/tm.hpp>
+#include <test/codemaker/cppumaker/singletons/std.hpp>
+#include <test/codemaker/cppumaker/singletons/NDEBUG.hpp>
+#include <test/codemaker/cppumaker/singletons/get.hpp>
+#include <test/codemaker/cppumaker/HelperEnum.hpp>
+#include <test/codemaker/cppumaker/HelperStruct.hpp>
+#include <test/codemaker/cppumaker/BigStruct.hpp>
+#include <test/codemaker/cppumaker/Struct.hpp>
+#include <test/codemaker/cppumaker/StructUsage.hpp>
+#include <test/codemaker/cppumaker/AlignmentDerivedStruct.hpp>
+#include <test/codemaker/cppumaker/TestException1.hpp>
+#include <test/codemaker/cppumaker/TestException2.hpp>
+#include <test/codemaker/cppumaker/Constants.hpp>
+
+#include <memory>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Type.hxx>
+#include <com/sun/star/uno/TypeClass.hpp>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <o3tl/cppunittraitshelper.hxx>
+#include <rtl/ustring.hxx>
+
+#include <cstddef>
+
+namespace test::codemaker::cppumaker {
+
+static bool operator ==(
+ test::codemaker::cppumaker::TestException1 const & e1,
+ test::codemaker::cppumaker::TestException1 const & e2)
+{
+ return e1.Message == e2.Message && e1.Context == e2.Context
+ && e1.m1 == e2.m1 && e1.m2 == e2.m2 && e1.m3 == e2.m3
+ && e1.m4.member1 == e2.m4.member1 && e1.m4.member2 == e2.m4.member2;
+}
+
+}
+
+namespace {
+
+class Test: public CppUnit::TestFixture {
+public:
+ void testBigStruct();
+
+ void testPolyStruct();
+
+ void testExceptions();
+
+ void testConstants();
+
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testBigStruct);
+ CPPUNIT_TEST(testPolyStruct);
+ CPPUNIT_TEST(testExceptions);
+ CPPUNIT_TEST(testConstants);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+struct Guard {
+ explicit Guard(void * buffer):
+ p(new(buffer) test::codemaker::cppumaker::BigStruct) {}
+
+ ~Guard() { p->test::codemaker::cppumaker::BigStruct::~BigStruct(); }
+
+ test::codemaker::cppumaker::BigStruct * const p;
+};
+
+void Test::testBigStruct() {
+ // Default-initialize a BigStruct instance on top of a memory buffer filled
+ // with random data, and make sure that all members are default-initialized:
+ std::unique_ptr< char []> buffer(
+ new char[sizeof (test::codemaker::cppumaker::BigStruct)]);
+ for (std::size_t i = 0; i < sizeof (test::codemaker::cppumaker::BigStruct);
+ ++i)
+ {
+ buffer[i] = '\x56';
+ }
+ Guard guard(buffer.get());
+ CPPUNIT_ASSERT_EQUAL(sal_False, guard.p->m1);
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int8 >(0), guard.p->m2);
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int16 >(0), guard.p->m3);
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_uInt16 >(0), guard.p->m4);
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int32 >(0), guard.p->m5);
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_uInt32 >(0), guard.p->m6);
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int64 >(0), guard.p->m7);
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_uInt64 >(0), guard.p->m8);
+ CPPUNIT_ASSERT_EQUAL(0.0f, guard.p->m9);
+ CPPUNIT_ASSERT_EQUAL(0.0, guard.p->m10);
+ CPPUNIT_ASSERT_EQUAL( u'\0', guard.p->m11);
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int32 >(0), guard.p->m12.getLength());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(css::uno::TypeClass_VOID), static_cast<sal_Int32>(guard.p->m13.getTypeClass()));
+ CPPUNIT_ASSERT_EQUAL(false, guard.p->m14.hasValue());
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int32 >(0), guard.p->m15.getLength());
+ CPPUNIT_ASSERT_EQUAL(int(test::codemaker::cppumaker::HelperEnum_ZERO), static_cast<int>(guard.p->m16));
+ CPPUNIT_ASSERT_EQUAL(sal_False, guard.p->m17.m1);
+ CPPUNIT_ASSERT_EQUAL(false, guard.p->m17.m2.is());
+ CPPUNIT_ASSERT_EQUAL(false, guard.p->m18.is());
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int8 >(0), guard.p->m19);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(test::codemaker::cppumaker::HelperEnum_ZERO), static_cast<sal_Int32>(guard.p->m20));
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int32 >(0), guard.p->m21.getLength());
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int32 >(0), guard.p->m22.getLength());
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int32 >(0), guard.p->m23.getLength());
+
+//This is a very platform specific test.
+#if defined __GNUC__ // see CPPU_GCC3_ALIGN
+#if defined(LINUX) && (defined (X86_64) || defined(X86) || defined(PPC))
+ static_assert(
+ sizeof (test::codemaker::cppumaker::AlignmentDerivedStruct) ==
+#if defined X86_64 || defined PPC
+ 24
+#else
+ 16
+#endif
+ );
+#endif
+#endif
+
+ css::uno::Type t(
+ cppu::UnoType< test::codemaker::cppumaker::BigStruct >::get());
+ typelib_TypeDescription * td = nullptr;
+ t.getDescription(&td);
+ typelib_typedescription_complete(&td);
+ fprintf(stdout, "#### 1\n");
+ CPPUNIT_ASSERT(td != nullptr);
+ CPPUNIT_ASSERT_EQUAL(+typelib_TypeClass_STRUCT, +td->eTypeClass);
+ typelib_StructTypeDescription * std =
+ reinterpret_cast< typelib_StructTypeDescription * >(td);
+ CPPUNIT_ASSERT_EQUAL(+typelib_TypeClass_UNSIGNED_SHORT, +std->aBase.ppTypeRefs[3]->eTypeClass); // unsigned short m4;
+ CPPUNIT_ASSERT_EQUAL(+typelib_TypeClass_CHAR, +std->aBase.ppTypeRefs[10]->eTypeClass); // char m11;
+}
+
+void Test::testPolyStruct() {
+ CPPUNIT_ASSERT_EQUAL(
+ OUString(
+ "test.codemaker.cppumaker.Struct<char,short>"),
+ (css::uno::Any(
+ test::codemaker::cppumaker::Struct< sal_Unicode, sal_Int16 >()).
+ getValueType().getTypeName()));
+
+ css::uno::Sequence< css::uno::Sequence< css::uno::Any > >
+ aEmptySequence;
+
+ CPPUNIT_ASSERT_EQUAL(
+ static_cast< sal_uInt32 >(5),
+ (test::codemaker::cppumaker::make_Struct< sal_uInt32, sal_Bool >(5,
+ aEmptySequence).member1));
+}
+
+void Test::testExceptions() {
+ css::uno::Sequence< css::uno::Sequence< css::uno::Any > >
+ aEmptySequence;
+
+ test::codemaker::cppumaker::TestException1 e11(
+ "abc", nullptr, 1,
+ css::uno::Any(123.0),
+ test::codemaker::cppumaker::HelperEnum_ONE,
+ test::codemaker::cppumaker::Struct<sal_Int32, sal_Int32>(5, aEmptySequence), 2);
+ test::codemaker::cppumaker::TestException1 e12(e11);
+ CPPUNIT_ASSERT_EQUAL(e11, e12);
+ test::codemaker::cppumaker::TestException1 e13;
+ e13 = e11;
+ CPPUNIT_ASSERT_EQUAL(e11, e13);
+ test::codemaker::cppumaker::TestException2 e21(
+ "abc", nullptr, 1,
+ css::uno::Any(123.0),
+ test::codemaker::cppumaker::HelperEnum_ONE,
+ test::codemaker::cppumaker::Struct<sal_Int32, sal_Int32>(5, aEmptySequence), 2);
+ test::codemaker::cppumaker::TestException2 e22(e21);
+ CPPUNIT_ASSERT_EQUAL(e21, e22);
+ test::codemaker::cppumaker::TestException2 e23;
+ e23 = e21;
+ CPPUNIT_ASSERT_EQUAL(e21, e23);
+}
+
+void Test::testConstants() {
+ CPPUNIT_ASSERT_EQUAL(
+ SAL_MIN_INT8, test::codemaker::cppumaker::Constants::byteMin);
+ CPPUNIT_ASSERT_EQUAL(
+ SAL_MAX_INT8, test::codemaker::cppumaker::Constants::byteMax);
+ CPPUNIT_ASSERT_EQUAL(
+ SAL_MIN_INT16, test::codemaker::cppumaker::Constants::shortMin);
+ CPPUNIT_ASSERT_EQUAL(
+ SAL_MAX_INT16, test::codemaker::cppumaker::Constants::shortMax);
+ CPPUNIT_ASSERT_EQUAL(
+ static_cast< sal_uInt16 >(0),
+ test::codemaker::cppumaker::Constants::unsignedShortMin);
+ CPPUNIT_ASSERT_EQUAL(
+ SAL_MAX_UINT16,
+ test::codemaker::cppumaker::Constants::unsignedShortMax);
+ CPPUNIT_ASSERT_EQUAL(
+ SAL_MIN_INT32, test::codemaker::cppumaker::Constants::longMin);
+ CPPUNIT_ASSERT_EQUAL(
+ SAL_MAX_INT32, test::codemaker::cppumaker::Constants::longMax);
+ CPPUNIT_ASSERT_EQUAL(
+ static_cast< sal_uInt32 >(0),
+ test::codemaker::cppumaker::Constants::unsignedLongMin);
+ CPPUNIT_ASSERT_EQUAL(
+ SAL_MAX_UINT32, test::codemaker::cppumaker::Constants::unsignedLongMax);
+ CPPUNIT_ASSERT_EQUAL(
+ SAL_MIN_INT64, test::codemaker::cppumaker::Constants::hyperMin);
+ CPPUNIT_ASSERT_EQUAL(
+ SAL_MAX_INT64, test::codemaker::cppumaker::Constants::hyperMax);
+ CPPUNIT_ASSERT_EQUAL(
+ static_cast< sal_uInt64 >(0),
+ test::codemaker::cppumaker::Constants::unsignedHyperMin);
+ CPPUNIT_ASSERT_EQUAL(
+ SAL_MAX_UINT64,
+ test::codemaker::cppumaker::Constants::unsignedHyperMax);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/qa/cppumaker/types.idl b/cppu/qa/cppumaker/types.idl
new file mode 100644
index 000000000..98ed1f867
--- /dev/null
+++ b/cppu/qa/cppumaker/types.idl
@@ -0,0 +1,710 @@
+/* -*- 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 .
+ */
+
+/*TODO: Do not depend on types for which C++ header files are only generated
+ later in the build process in offuh: */
+#include <com/sun/star/lang/ClassNotFoundException.idl>
+#include <com/sun/star/lang/IllegalAccessException.idl>
+#include <com/sun/star/lang/Locale.idl>
+#include <com/sun/star/uno/DeploymentException.idl>
+#include <com/sun/star/uno/Exception.idl>
+#include <com/sun/star/uno/RuntimeException.idl>
+#include <com/sun/star/uno/XInterface.idl>
+#include <com/sun/star/uno/XNamingService.idl>
+
+singleton FILE: com::sun::star::uno::XInterface;
+singleton lconv: com::sun::star::uno::XInterface;
+singleton tm: com::sun::star::uno::XInterface;
+
+singleton std: com::sun::star::uno::XInterface;
+
+module test { module codemaker { module cppumaker {
+
+interface XTest {
+ boolean test();
+
+ [attribute, bound] long A1;
+ [attribute, bound, readonly] long A2;
+ [attribute] long A3 {
+ get raises
+ (com::sun::star::uno::Exception,
+ com::sun::star::lang::ClassNotFoundException);
+ set raises (com::sun::star::uno::RuntimeException);
+ };
+ [attribute, readonly] long A4 {
+ get raises (com::sun::star::uno::DeploymentException);
+ };
+};
+
+typedef boolean Boolean;
+typedef byte Byte;
+typedef short Short;
+typedef unsigned short UnsignedShort;
+typedef long Long;
+typedef unsigned long UnsignedLong;
+typedef hyper Hyper;
+typedef unsigned hyper UnsignedHyper;
+typedef float Float;
+typedef double Double;
+typedef char Char;
+typedef string String;
+typedef type Type;
+typedef any Any;
+typedef com::sun::star::lang::Locale Locale;
+typedef com::sun::star::uno::XInterface XInterface;
+typedef com::sun::star::uno::XNamingService XNamingService;
+
+typedef sequence< Boolean > SequenceBoolean;
+typedef sequence< Byte > SequenceByte;
+typedef sequence< Short > SequenceShort;
+typedef sequence< UnsignedShort > SequenceUnsignedShort;
+typedef sequence< Long > SequenceLong;
+typedef sequence< UnsignedLong > SequenceUnsignedLong;
+typedef sequence< Hyper > SequenceHyper;
+typedef sequence< UnsignedHyper > SequenceUnsignedHyper;
+typedef sequence< Float > SequenceFloat;
+typedef sequence< Double > SequenceDouble;
+typedef sequence< Char > SequenceChar;
+typedef sequence< String > SequenceString;
+typedef sequence< Type > SequenceType;
+typedef sequence< Any > SequenceAny;
+typedef sequence< Locale > SequenceLocale;
+typedef sequence< XInterface > SequenceXInterface;
+typedef sequence< XNamingService > SequenceXNamingService;
+
+service S1: XTest {
+ create1();
+
+ create2([in] any... create2)
+ raises (com::sun::star::uno::RuntimeException,
+ com::sun::star::lang::ClassNotFoundException,
+ com::sun::star::uno::Exception,
+ com::sun::star::lang::IllegalAccessException,
+ com::sun::star::uno::DeploymentException);
+
+ create3([in] sequence<any> S1)
+ raises (com::sun::star::uno::RuntimeException,
+ com::sun::star::lang::ClassNotFoundException,
+ com::sun::star::lang::IllegalAccessException,
+ com::sun::star::uno::DeploymentException);
+
+ create4([in] long javamaker, [in] long S1, [in] long create4);
+
+ create5(
+ [in] boolean p1,
+ [in] byte p2,
+ [in] short p3,
+ [in] unsigned short p4,
+ [in] long p5,
+ [in] unsigned long p6,
+ [in] hyper p7,
+ [in] unsigned hyper p8,
+ [in] float p9,
+ [in] double p10,
+ [in] char p11,
+ [in] string p12,
+ [in] type p13,
+ [in] any p14,
+ [in] com::sun::star::lang::Locale p15,
+ [in] com::sun::star::uno::XInterface p16,
+ [in] com::sun::star::uno::XNamingService p17,
+ [in] Boolean t1,
+ [in] Byte t2,
+ [in] Short t3,
+ [in] UnsignedShort t4,
+ [in] Long t5,
+ [in] UnsignedLong t6,
+ [in] Hyper t7,
+ [in] UnsignedHyper t8,
+ [in] Float t9,
+ [in] Double t10,
+ [in] Char t11,
+ [in] String t12,
+ [in] Type t13,
+ [in] Any t14,
+ [in] Locale t15,
+ [in] XInterface t16,
+ [in] XNamingService t17,
+ [in] sequence< sequence< boolean > > a1,
+ [in] sequence< sequence< byte > > a2,
+ [in] sequence< sequence< short > > a3,
+ [in] sequence< sequence< unsigned short > > a4,
+ [in] sequence< sequence< long > > a5,
+ [in] sequence< sequence< unsigned long > > a6,
+ [in] sequence< sequence< hyper > > a7,
+ [in] sequence< sequence< unsigned hyper > > a8,
+ [in] sequence< sequence< float > > a9,
+ [in] sequence< sequence< double > > a10,
+ [in] sequence< sequence< char > > a11,
+ [in] sequence< sequence< string > > a12,
+ [in] sequence< sequence< type > > a13,
+ [in] sequence< sequence< any > > a14,
+ [in] sequence< sequence< com::sun::star::lang::Locale > > a15,
+ [in] sequence< sequence< com::sun::star::uno::XInterface > > a16,
+ [in] sequence< sequence<
+ com::sun::star::uno::XNamingService > > a17,
+ [in] sequence< SequenceBoolean > at1,
+ [in] sequence< SequenceByte > at2,
+ [in] sequence< SequenceShort > at3,
+ [in] sequence< SequenceUnsignedShort > at4,
+ [in] sequence< SequenceLong > at5,
+ [in] sequence< SequenceUnsignedLong > at6,
+ [in] sequence< SequenceHyper > at7,
+ [in] sequence< SequenceUnsignedHyper > at8,
+ [in] sequence< SequenceFloat > at9,
+ [in] sequence< SequenceDouble > at10,
+ [in] sequence< SequenceChar > at11,
+ [in] sequence< SequenceString > at12,
+ [in] sequence< SequenceType > at13,
+ [in] sequence< SequenceAny > at14,
+ [in] sequence< SequenceLocale > at15,
+ [in] sequence< SequenceXInterface > at16,
+ [in] sequence< SequenceXNamingService > at17);
+};
+
+service S2: XTest;
+
+service S3 { interface XTest; };
+
+singleton S4 { service S3; };
+
+module services {
+
+service asm: com::sun::star::uno::XInterface { asm([in] long asm); };
+service auto: com::sun::star::uno::XInterface { auto([in] long auto); };
+service bool: com::sun::star::uno::XInterface { bool([in] long bool); };
+service break: com::sun::star::uno::XInterface { break([in] long break); };
+//TODO: service case: com::sun::star::uno::XInterface { case([in] long case); };
+service catch: com::sun::star::uno::XInterface { catch([in] long catch); };
+//TODO: service char: com::sun::star::uno::XInterface { char([in] long char); };
+service class: com::sun::star::uno::XInterface { class([in] long class); };
+//TODO: service const: com::sun::star::uno::XInterface {
+// const([in] long const); };
+service continue: com::sun::star::uno::XInterface {
+ continue([in] long continue); };
+//TODO: service default: com::sun::star::uno::XInterface {
+// default([in] long default); };
+service delete: com::sun::star::uno::XInterface { delete([in] long delete); };
+service do: com::sun::star::uno::XInterface { do([in] long do); };
+//TODO: service double: com::sun::star::uno::XInterface {
+// double([in] long double); };
+service else: com::sun::star::uno::XInterface { else([in] long else); };
+//TODO: service enum: com::sun::star::uno::XInterface { enum([in] long enum); };
+service explicit: com::sun::star::uno::XInterface {
+ explicit([in] long explicit); };
+service export: com::sun::star::uno::XInterface { export([in] long export); };
+service extern: com::sun::star::uno::XInterface { extern([in] long extern); };
+service false: com::sun::star::uno::XInterface { false([in] long false); };
+//TODO: service float: com::sun::star::uno::XInterface {
+// float([in] long float); };
+service for: com::sun::star::uno::XInterface { for([in] long for); };
+service friend: com::sun::star::uno::XInterface { friend([in] long friend); };
+service goto: com::sun::star::uno::XInterface { goto([in] long goto); };
+service if: com::sun::star::uno::XInterface { if([in] long if); };
+service inline: com::sun::star::uno::XInterface { inline([in] long inline); };
+service int: com::sun::star::uno::XInterface { int([in] long int); };
+//TODO: service long: com::sun::star::uno::XInterface { long([in] long long); };
+service mutable: com::sun::star::uno::XInterface {
+ mutable([in] long mutable); };
+service namespace: com::sun::star::uno::XInterface {
+ namespace([in] long namespace); };
+service new: com::sun::star::uno::XInterface { new([in] long new); };
+service operator: com::sun::star::uno::XInterface {
+ operator([in] long operator); };
+service private: com::sun::star::uno::XInterface {
+ private([in] long private); };
+service protected: com::sun::star::uno::XInterface {
+ protected([in] long protected); };
+service public: com::sun::star::uno::XInterface { public([in] long public); };
+service register: com::sun::star::uno::XInterface {
+ register([in] long register); };
+service return: com::sun::star::uno::XInterface { return([in] long return); };
+//TODO: service short: com::sun::star::uno::XInterface {
+// short([in] long short); };
+service signed: com::sun::star::uno::XInterface { signed([in] long signed); };
+service sizeof: com::sun::star::uno::XInterface { sizeof([in] long sizeof); };
+service static: com::sun::star::uno::XInterface { static([in] long static); };
+//TODO: service struct: com::sun::star::uno::XInterface {
+// struct([in] long struct); };
+//TODO: service switch: com::sun::star::uno::XInterface {
+// switch([in] long switch); };
+service template: com::sun::star::uno::XInterface {
+ template([in] long template); };
+service this: com::sun::star::uno::XInterface { this([in] long this); };
+service throw: com::sun::star::uno::XInterface { throw([in] long throw); };
+service true: com::sun::star::uno::XInterface { true([in] long true); };
+service try: com::sun::star::uno::XInterface { try([in] long try); };
+//TODO: service typedef: com::sun::star::uno::XInterface {
+// typedef([in] long typedef); };
+service typeid: com::sun::star::uno::XInterface { typeid([in] long typeid); };
+service typename: com::sun::star::uno::XInterface {
+ typename([in] long typename); };
+//TODO: service union: com::sun::star::uno::XInterface {
+// union([in] long union); };
+//TODO: service unsigned: com::sun::star::uno::XInterface {
+// unsigned([in] long unsigned); };
+service using: com::sun::star::uno::XInterface { using([in] long using); };
+service virtual: com::sun::star::uno::XInterface {
+ virtual([in] long virtual); };
+//TODO: service void: com::sun::star::uno::XInterface { void([in] long void); };
+service volatile: com::sun::star::uno::XInterface {
+ volatile([in] long volatile); };
+service while: com::sun::star::uno::XInterface { while([in] long while); };
+
+service and: com::sun::star::uno::XInterface { and([in] long and); };
+service bitand: com::sun::star::uno::XInterface { bitand([in] long bitand); };
+service bitor: com::sun::star::uno::XInterface { bitor([in] long bitor); };
+service compl: com::sun::star::uno::XInterface { compl([in] long compl); };
+service not: com::sun::star::uno::XInterface { not([in] long not); };
+service or: com::sun::star::uno::XInterface { or([in] long or); };
+service xor: com::sun::star::uno::XInterface { xor([in] long xor); };
+
+service BUFSIZ: com::sun::star::uno::XInterface { BUFSIZ([in] long BUFSIZ); };
+service CLOCKS_PER_SEC: com::sun::star::uno::XInterface {
+ CLOCKS_PER_SEC([in] long CLOCKS_PER_SEC); };
+service EDOM: com::sun::star::uno::XInterface { EDOM([in] long EDOM); };
+service EOF: com::sun::star::uno::XInterface { EOF([in] long EOF); };
+service ERANGE: com::sun::star::uno::XInterface { ERANGE([in] long ERANGE); };
+service EXIT_FAILURE: com::sun::star::uno::XInterface {
+ EXIT_FAILURE([in] long EXIT_FAILURE); };
+service EXIT_SUCCESS: com::sun::star::uno::XInterface {
+ EXIT_SUCCESS([in] long EXIT_SUCCESS); };
+service FILENAME_MAX: com::sun::star::uno::XInterface {
+ FILENAME_MAX([in] long FILENAME_MAX); };
+service FOPEN_MAX: com::sun::star::uno::XInterface {
+ FOPEN_MAX([in] long FOPEN_MAX); };
+service HUGE_VAL: com::sun::star::uno::XInterface {
+ HUGE_VAL([in] long HUGE_VAL); };
+service LC_ALL: com::sun::star::uno::XInterface { LC_ALL([in] long LC_ALL); };
+service LC_COLLATE: com::sun::star::uno::XInterface {
+ LC_COLLATE([in] long LC_COLLATE); };
+service LC_CTYPE: com::sun::star::uno::XInterface {
+ LC_CTYPE([in] long LC_CTYPE); };
+service LC_MONETARY: com::sun::star::uno::XInterface {
+ LC_MONETARY([in] long LC_MONETARY); };
+service LC_NUMERIC: com::sun::star::uno::XInterface {
+ LC_NUMERIC([in] long LC_NUMERIC); };
+service LC_TIME: com::sun::star::uno::XInterface {
+ LC_TIME([in] long LC_TIME); };
+service L_tmpnam: com::sun::star::uno::XInterface {
+ L_tmpnam([in] long L_tmpnam); };
+service MB_CUR_MAX: com::sun::star::uno::XInterface {
+ MB_CUR_MAX([in] long MB_CUR_MAX); };
+service NULL: com::sun::star::uno::XInterface { NULL([in] long NULL); };
+service RAND_MAX: com::sun::star::uno::XInterface {
+ RAND_MAX([in] long RAND_MAX); };
+service SEEK_CUR: com::sun::star::uno::XInterface {
+ SEEK_CUR([in] long SEEK_CUR); };
+service SEEK_END: com::sun::star::uno::XInterface {
+ SEEK_END([in] long SEEK_END); };
+service SEEK_SET: com::sun::star::uno::XInterface {
+ SEEK_SET([in] long SEEK_SET); };
+service SIGABRT: com::sun::star::uno::XInterface {
+ SIGABRT([in] long SIGABRT); };
+service SIGFPE: com::sun::star::uno::XInterface { SIGFPE([in] long SIGFPE); };
+service SIGILL: com::sun::star::uno::XInterface { SIGILL([in] long SIGILL); };
+service SIGINT: com::sun::star::uno::XInterface { SIGINT([in] long SIGINT); };
+service SIGSEGV: com::sun::star::uno::XInterface {
+ SIGSEGV([in] long SIGSEGV); };
+service SIGTERM: com::sun::star::uno::XInterface {
+ SIGTERM([in] long SIGTERM); };
+service SIG_DFL: com::sun::star::uno::XInterface {
+ SIG_DFL([in] long SIG_DFL); };
+service SIG_ERR: com::sun::star::uno::XInterface {
+ SIG_ERR([in] long SIG_ERR); };
+service SIG_IGN: com::sun::star::uno::XInterface {
+ SIG_IGN([in] long SIG_IGN); };
+service TMP_MAX: com::sun::star::uno::XInterface {
+ TMP_MAX([in] long TMP_MAX); };
+service WCHAR_MAX: com::sun::star::uno::XInterface {
+ WCHAR_MAX([in] long WCHAR_MAX); };
+service WCHAR_MIN: com::sun::star::uno::XInterface {
+ WCHAR_MIN([in] long WCHAR_MIN); };
+service WEOF: com::sun::star::uno::XInterface { WEOF([in] long WEOF); };
+service assert: com::sun::star::uno::XInterface { assert([in] long assert); };
+service errno: com::sun::star::uno::XInterface { errno([in] long errno); };
+service offsetof: com::sun::star::uno::XInterface {
+ offsetof([in] long offsetof); };
+service setjmp: com::sun::star::uno::XInterface { setjmp([in] long setjmp); };
+service stderr: com::sun::star::uno::XInterface { stderr([in] long stderr); };
+service stdin: com::sun::star::uno::XInterface { stdin([in] long stdin); };
+service stdout: com::sun::star::uno::XInterface { stdout([in] long stdout); };
+
+service CHAR_BIT: com::sun::star::uno::XInterface {
+ CHAR_BIT([in] long CHAR_BIT); };
+service CHAR_MAX: com::sun::star::uno::XInterface {
+ CHAR_MAX([in] long CHAR_MAX); };
+service CHAR_MIN: com::sun::star::uno::XInterface {
+ CHAR_MIN([in] long CHAR_MIN); };
+service DBL_DIG: com::sun::star::uno::XInterface {
+ DBL_DIG([in] long DBL_DIG); };
+service DBL_EPSILON: com::sun::star::uno::XInterface {
+ DBL_EPSILON([in] long DBL_EPSILON); };
+service DBL_MANT_DIG: com::sun::star::uno::XInterface {
+ DBL_MANT_DIG([in] long DBL_MANT_DIG); };
+service DBL_MAX: com::sun::star::uno::XInterface {
+ DBL_MAX([in] long DBL_MAX); };
+service DBL_MAX_10_EXP: com::sun::star::uno::XInterface {
+ DBL_MAX_10_EXP([in] long DBL_MAX_10_EXP); };
+service DBL_MAX_EXP: com::sun::star::uno::XInterface {
+ DBL_MAX_EXP([in] long DBL_MAX_EXP); };
+service DBL_MIN: com::sun::star::uno::XInterface {
+ DBL_MIN([in] long DBL_MIN); };
+service DBL_MIN_10_EXP: com::sun::star::uno::XInterface {
+ DBL_MIN_10_EXP([in] long DBL_MIN_10_EXP); };
+service DBL_MIN_EXP: com::sun::star::uno::XInterface {
+ DBL_MIN_EXP([in] long DBL_MIN_EXP); };
+service FLT_DIG: com::sun::star::uno::XInterface {
+ FLT_DIG([in] long FLT_DIG); };
+service FLT_EPSILON: com::sun::star::uno::XInterface {
+ FLT_EPSILON([in] long FLT_EPSILON); };
+service FLT_MANT_DIG: com::sun::star::uno::XInterface {
+ FLT_MANT_DIG([in] long FLT_MANT_DIG); };
+service FLT_MAX: com::sun::star::uno::XInterface {
+ FLT_MAX([in] long FLT_MAX); };
+service FLT_MAX_10_EXP: com::sun::star::uno::XInterface {
+ FLT_MAX_10_EXP([in] long FLT_MAX_10_EXP); };
+service FLT_MAX_EXP: com::sun::star::uno::XInterface {
+ FLT_MAX_EXP([in] long FLT_MAX_EXP); };
+service FLT_MIN: com::sun::star::uno::XInterface {
+ FLT_MIN([in] long FLT_MIN); };
+service FLT_MIN_10_EXP: com::sun::star::uno::XInterface {
+ FLT_MIN_10_EXP([in] long FLT_MIN_10_EXP); };
+service FLT_MIN_EXP: com::sun::star::uno::XInterface {
+ FLT_MIN_EXP([in] long FLT_MIN_EXP); };
+service FLT_RADIX: com::sun::star::uno::XInterface {
+ FLT_RADIX([in] long FLT_RADIX); };
+service FLT_ROUNDS: com::sun::star::uno::XInterface {
+ FLT_ROUNDS([in] long FLT_ROUNDS); };
+service INT_MAX: com::sun::star::uno::XInterface {
+ INT_MAX([in] long INT_MAX); };
+service INT_MIN: com::sun::star::uno::XInterface {
+ INT_MIN([in] long INT_MIN); };
+service LDBL_DIG: com::sun::star::uno::XInterface {
+ LDBL_DIG([in] long LDBL_DIG); };
+service LDBL_EPSILON: com::sun::star::uno::XInterface {
+ LDBL_EPSILON([in] long LDBL_EPSILON); };
+service LDBL_MANT_DIG: com::sun::star::uno::XInterface {
+ LDBL_MANT_DIG([in] long LDBL_MANT_DIG); };
+service LDBL_MAX: com::sun::star::uno::XInterface {
+ LDBL_MAX([in] long LDBL_MAX); };
+service LDBL_MAX_10_EXP: com::sun::star::uno::XInterface {
+ LDBL_MAX_10_EXP([in] long LDBL_MAX_10_EXP); };
+service LDBL_MAX_EXP: com::sun::star::uno::XInterface {
+ LDBL_MAX_EXP([in] long LDBL_MAX_EXP); };
+service LDBL_MIN: com::sun::star::uno::XInterface {
+ LDBL_MIN([in] long LDBL_MIN); };
+service LDBL_MIN_10_EXP: com::sun::star::uno::XInterface {
+ LDBL_MIN_10_EXP([in] long LDBL_MIN_10_EXP); };
+service LDBL_MIN_EXP: com::sun::star::uno::XInterface {
+ LDBL_MIN_EXP([in] long LDBL_MIN_EXP); };
+service LONG_MAX: com::sun::star::uno::XInterface {
+ LONG_MAX([in] long LONG_MAX); };
+service LONG_MIN: com::sun::star::uno::XInterface {
+ LONG_MIN([in] long LONG_MIN); };
+service MB_LEN_MAX: com::sun::star::uno::XInterface {
+ MB_LEN_MAX([in] long MB_LEN_MAX); };
+service SCHAR_MAX: com::sun::star::uno::XInterface {
+ SCHAR_MAX([in] long SCHAR_MAX); };
+service SCHAR_MIN: com::sun::star::uno::XInterface {
+ SCHAR_MIN([in] long SCHAR_MIN); };
+service SHRT_MAX: com::sun::star::uno::XInterface {
+ SHRT_MAX([in] long SHRT_MAX); };
+service SHRT_MIN: com::sun::star::uno::XInterface {
+ SHRT_MIN([in] long SHRT_MIN); };
+service UCHAR_MAX: com::sun::star::uno::XInterface {
+ UCHAR_MAX([in] long UCHAR_MAX); };
+service UINT_MAX: com::sun::star::uno::XInterface {
+ UINT_MAX([in] long UINT_MAX); };
+service ULONG_MAX: com::sun::star::uno::XInterface {
+ ULONG_MAX([in] long ULONG_MAX); };
+service USHRT_MAX: com::sun::star::uno::XInterface {
+ USHRT_MAX([in] long USHRT_MAX); };
+
+service FILE: com::sun::star::uno::XInterface { FILE([in] long FILE); };
+service lconv: com::sun::star::uno::XInterface { lconv([in] long lconv); };
+service tm: com::sun::star::uno::XInterface { tm([in] long tm); };
+
+service std: com::sun::star::uno::XInterface { std([in] long std); };
+
+service NDEBUG: com::sun::star::uno::XInterface { NDEBUG([in] long NDEBUG); };
+
+service create: com::sun::star::uno::XInterface;
+
+};
+
+module singletons {
+
+singleton asm: com::sun::star::uno::XInterface;
+singleton auto: com::sun::star::uno::XInterface;
+singleton bool: com::sun::star::uno::XInterface;
+singleton break: com::sun::star::uno::XInterface;
+//TODO: singleton case: com::sun::star::uno::XInterface;
+singleton catch: com::sun::star::uno::XInterface;
+//TODO: singleton char: com::sun::star::uno::XInterface;
+singleton class: com::sun::star::uno::XInterface;
+//TODO: singleton const: com::sun::star::uno::XInterface;
+singleton continue: com::sun::star::uno::XInterface;
+//TODO: singleton default: com::sun::star::uno::XInterface;
+singleton delete: com::sun::star::uno::XInterface;
+singleton do: com::sun::star::uno::XInterface;
+//TODO: singleton double: com::sun::star::uno::XInterface;
+singleton else: com::sun::star::uno::XInterface;
+//TODO: singleton enum: com::sun::star::uno::XInterface;
+singleton explicit: com::sun::star::uno::XInterface;
+singleton export: com::sun::star::uno::XInterface;
+singleton extern: com::sun::star::uno::XInterface;
+singleton false: com::sun::star::uno::XInterface;
+//TODO: singleton float: com::sun::star::uno::XInterface;
+singleton for: com::sun::star::uno::XInterface;
+singleton friend: com::sun::star::uno::XInterface;
+singleton goto: com::sun::star::uno::XInterface;
+singleton if: com::sun::star::uno::XInterface;
+singleton inline: com::sun::star::uno::XInterface;
+singleton int: com::sun::star::uno::XInterface;
+//TODO: singleton long: com::sun::star::uno::XInterface;
+singleton mutable: com::sun::star::uno::XInterface;
+singleton namespace: com::sun::star::uno::XInterface;
+singleton new: com::sun::star::uno::XInterface;
+singleton operator: com::sun::star::uno::XInterface;
+singleton private: com::sun::star::uno::XInterface;
+singleton protected: com::sun::star::uno::XInterface;
+singleton public: com::sun::star::uno::XInterface;
+singleton register: com::sun::star::uno::XInterface;
+singleton return: com::sun::star::uno::XInterface;
+//TODO: singleton short: com::sun::star::uno::XInterface;
+singleton signed: com::sun::star::uno::XInterface;
+singleton sizeof: com::sun::star::uno::XInterface;
+singleton static: com::sun::star::uno::XInterface;
+//TODO: singleton struct: com::sun::star::uno::XInterface;
+//TODO: singleton switch: com::sun::star::uno::XInterface;
+singleton template: com::sun::star::uno::XInterface;
+singleton this: com::sun::star::uno::XInterface;
+singleton throw: com::sun::star::uno::XInterface;
+singleton true: com::sun::star::uno::XInterface;
+singleton try: com::sun::star::uno::XInterface;
+//TODO: singleton typedef: com::sun::star::uno::XInterface;
+singleton typeid: com::sun::star::uno::XInterface;
+singleton typename: com::sun::star::uno::XInterface;
+//TODO: singleton union: com::sun::star::uno::XInterface;
+//TODO: singleton unsigned: com::sun::star::uno::XInterface;
+singleton using: com::sun::star::uno::XInterface;
+singleton virtual: com::sun::star::uno::XInterface;
+//TODO: singleton void: com::sun::star::uno::XInterface;
+singleton volatile: com::sun::star::uno::XInterface;
+singleton while: com::sun::star::uno::XInterface;
+
+singleton and: com::sun::star::uno::XInterface;
+singleton bitand: com::sun::star::uno::XInterface;
+singleton bitor: com::sun::star::uno::XInterface;
+singleton compl: com::sun::star::uno::XInterface;
+singleton not: com::sun::star::uno::XInterface;
+singleton or: com::sun::star::uno::XInterface;
+singleton xor: com::sun::star::uno::XInterface;
+
+singleton BUFSIZ: com::sun::star::uno::XInterface;
+singleton CLOCKS_PER_SEC: com::sun::star::uno::XInterface;
+singleton EDOM: com::sun::star::uno::XInterface;
+singleton EOF: com::sun::star::uno::XInterface;
+singleton ERANGE: com::sun::star::uno::XInterface;
+singleton EXIT_FAILURE: com::sun::star::uno::XInterface;
+singleton EXIT_SUCCESS: com::sun::star::uno::XInterface;
+singleton FILENAME_MAX: com::sun::star::uno::XInterface;
+singleton FOPEN_MAX: com::sun::star::uno::XInterface;
+singleton HUGE_VAL: com::sun::star::uno::XInterface;
+singleton LC_ALL: com::sun::star::uno::XInterface;
+singleton LC_COLLATE: com::sun::star::uno::XInterface;
+singleton LC_CTYPE: com::sun::star::uno::XInterface;
+singleton LC_MONETARY: com::sun::star::uno::XInterface;
+singleton LC_NUMERIC: com::sun::star::uno::XInterface;
+singleton LC_TIME: com::sun::star::uno::XInterface;
+singleton L_tmpnam: com::sun::star::uno::XInterface;
+singleton MB_CUR_MAX: com::sun::star::uno::XInterface;
+singleton NULL: com::sun::star::uno::XInterface;
+singleton RAND_MAX: com::sun::star::uno::XInterface;
+singleton SEEK_CUR: com::sun::star::uno::XInterface;
+singleton SEEK_END: com::sun::star::uno::XInterface;
+singleton SEEK_SET: com::sun::star::uno::XInterface;
+singleton SIGABRT: com::sun::star::uno::XInterface;
+singleton SIGFPE: com::sun::star::uno::XInterface;
+singleton SIGILL: com::sun::star::uno::XInterface;
+singleton SIGINT: com::sun::star::uno::XInterface;
+singleton SIGSEGV: com::sun::star::uno::XInterface;
+singleton SIGTERM: com::sun::star::uno::XInterface;
+singleton SIG_DFL: com::sun::star::uno::XInterface;
+singleton SIG_ERR: com::sun::star::uno::XInterface;
+singleton SIG_IGN: com::sun::star::uno::XInterface;
+singleton TMP_MAX: com::sun::star::uno::XInterface;
+singleton WCHAR_MAX: com::sun::star::uno::XInterface;
+singleton WCHAR_MIN: com::sun::star::uno::XInterface;
+singleton WEOF: com::sun::star::uno::XInterface;
+singleton assert: com::sun::star::uno::XInterface;
+singleton errno: com::sun::star::uno::XInterface;
+singleton offsetof: com::sun::star::uno::XInterface;
+singleton setjmp: com::sun::star::uno::XInterface;
+singleton stderr: com::sun::star::uno::XInterface;
+singleton stdin: com::sun::star::uno::XInterface;
+singleton stdout: com::sun::star::uno::XInterface;
+
+singleton CHAR_BIT: com::sun::star::uno::XInterface;
+singleton CHAR_MAX: com::sun::star::uno::XInterface;
+singleton CHAR_MIN: com::sun::star::uno::XInterface;
+singleton DBL_DIG: com::sun::star::uno::XInterface;
+singleton DBL_EPSILON: com::sun::star::uno::XInterface;
+singleton DBL_MANT_DIG: com::sun::star::uno::XInterface;
+singleton DBL_MAX: com::sun::star::uno::XInterface;
+singleton DBL_MAX_10_EXP: com::sun::star::uno::XInterface;
+singleton DBL_MAX_EXP: com::sun::star::uno::XInterface;
+singleton DBL_MIN: com::sun::star::uno::XInterface;
+singleton DBL_MIN_10_EXP: com::sun::star::uno::XInterface;
+singleton DBL_MIN_EXP: com::sun::star::uno::XInterface;
+singleton FLT_DIG: com::sun::star::uno::XInterface;
+singleton FLT_EPSILON: com::sun::star::uno::XInterface;
+singleton FLT_MANT_DIG: com::sun::star::uno::XInterface;
+singleton FLT_MAX: com::sun::star::uno::XInterface;
+singleton FLT_MAX_10_EXP: com::sun::star::uno::XInterface;
+singleton FLT_MAX_EXP: com::sun::star::uno::XInterface;
+singleton FLT_MIN: com::sun::star::uno::XInterface;
+singleton FLT_MIN_10_EXP: com::sun::star::uno::XInterface;
+singleton FLT_MIN_EXP: com::sun::star::uno::XInterface;
+singleton FLT_RADIX: com::sun::star::uno::XInterface;
+singleton FLT_ROUNDS: com::sun::star::uno::XInterface;
+singleton INT_MAX: com::sun::star::uno::XInterface;
+singleton INT_MIN: com::sun::star::uno::XInterface;
+singleton LDBL_DIG: com::sun::star::uno::XInterface;
+singleton LDBL_EPSILON: com::sun::star::uno::XInterface;
+singleton LDBL_MANT_DIG: com::sun::star::uno::XInterface;
+singleton LDBL_MAX: com::sun::star::uno::XInterface;
+singleton LDBL_MAX_10_EXP: com::sun::star::uno::XInterface;
+singleton LDBL_MAX_EXP: com::sun::star::uno::XInterface;
+singleton LDBL_MIN: com::sun::star::uno::XInterface;
+singleton LDBL_MIN_10_EXP: com::sun::star::uno::XInterface;
+singleton LDBL_MIN_EXP: com::sun::star::uno::XInterface;
+singleton LONG_MAX: com::sun::star::uno::XInterface;
+singleton LONG_MIN: com::sun::star::uno::XInterface;
+singleton MB_LEN_MAX: com::sun::star::uno::XInterface;
+singleton SCHAR_MAX: com::sun::star::uno::XInterface;
+singleton SCHAR_MIN: com::sun::star::uno::XInterface;
+singleton SHRT_MAX: com::sun::star::uno::XInterface;
+singleton SHRT_MIN: com::sun::star::uno::XInterface;
+singleton UCHAR_MAX: com::sun::star::uno::XInterface;
+singleton UINT_MAX: com::sun::star::uno::XInterface;
+singleton ULONG_MAX: com::sun::star::uno::XInterface;
+singleton USHRT_MAX: com::sun::star::uno::XInterface;
+
+singleton FILE: com::sun::star::uno::XInterface;
+singleton lconv: com::sun::star::uno::XInterface;
+singleton tm: com::sun::star::uno::XInterface;
+
+singleton std: com::sun::star::uno::XInterface;
+
+singleton NDEBUG: com::sun::star::uno::XInterface;
+
+singleton get: com::sun::star::uno::XInterface;
+
+};
+
+enum HelperEnum { ZERO, ONE };
+
+struct HelperStruct { boolean m1; com::sun::star::uno::XInterface m2; };
+
+typedef byte TDByte;
+typedef HelperEnum TDEnum1;
+typedef TDEnum1 TDEnum;
+
+struct BigStruct {
+ boolean m1;
+ byte m2;
+ short m3;
+ unsigned short m4;
+ long m5;
+ unsigned long m6;
+ hyper m7;
+ unsigned hyper m8;
+ float m9;
+ double m10;
+ char m11;
+ string m12;
+ type m13;
+ any m14;
+ sequence<boolean> m15;
+ HelperEnum m16;
+ HelperStruct m17;
+ com::sun::star::uno::XInterface m18;
+ TDByte m19;
+ TDEnum m20;
+ sequence<unsigned short> m21;
+ sequence<char> m22;
+ sequence< sequence<char> > m23;
+};
+
+struct Struct<T, U> {
+ T member1;
+ sequence<SequenceAny> member2;
+};
+
+struct StructUsage {
+ Struct< long, short > member1;
+ sequence<
+ sequence<
+ Struct<
+ sequence< Struct< any, boolean > >,
+ com::sun::star::uno::XInterface > > >
+ member2;
+};
+
+struct AlignmentBaseStruct {
+ double member1;
+ short member2;
+};
+
+struct AlignmentDerivedStruct: AlignmentBaseStruct {
+ short member3;
+};
+
+exception TestException1: com::sun::star::uno::RuntimeException {
+ long m1;
+ any m2;
+ HelperEnum m3;
+ Struct<long, long> m4;
+ unsigned short m5;
+};
+
+exception TestException2: TestException1 {};
+
+constants Constants {
+ const byte byteMin = -128;
+ const byte byteMax = 127;
+ const short shortMin = -32768;
+ const short shortMax = 32767;
+ const unsigned short unsignedShortMin = 0;
+ const unsigned short unsignedShortMax = 65535;
+ const long longMin = -2147483648;
+ const long longMax = 2147483647;
+ const unsigned long unsignedLongMin = 0;
+ const unsigned long unsignedLongMax = 4294967295;
+ const hyper hyperMin = -9223372036854775808;
+ const hyper hyperMax = 9223372036854775807;
+ const unsigned hyper unsignedHyperMin = 0;
+ const unsigned hyper unsignedHyperMax = 18446744073709551615;
+};
+
+}; }; };
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/qa/test_any.cxx b/cppu/qa/test_any.cxx
new file mode 100644
index 000000000..757040314
--- /dev/null
+++ b/cppu/qa/test_any.cxx
@@ -0,0 +1,2578 @@
+/* -*- 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 <stdlib.h>
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <Enum1.hpp>
+#include <Enum2.hpp>
+#include <Exception1.hpp>
+#include <Exception2.hpp>
+#include <Exception2a.hpp>
+#include <Exception2b.hpp>
+#include <Interface1.hpp>
+#include <Interface2.hpp>
+#include <Interface2a.hpp>
+#include <Interface2b.hpp>
+#include <Interface3.hpp>
+#include <Poly.hpp>
+#include <Struct1.hpp>
+#include <Struct2.hpp>
+#include <Struct2a.hpp>
+#include <Struct2b.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Type.hxx>
+#include <o3tl/cppunittraitshelper.hxx>
+#include <osl/interlck.h>
+#include <rtl/ustring.hxx>
+
+namespace {
+
+class Base {
+public:
+ Base(): m_count(0) {}
+
+ Base(const Base&) = delete;
+ const Base& operator=(const Base&) = delete;
+
+ void acquire() {
+ if (osl_atomic_increment(&m_count) == SAL_MAX_INT32) {
+ abort();
+ }
+ }
+
+ void release() {
+ if (osl_atomic_decrement(&m_count) == 0) {
+ delete this;
+ }
+ }
+
+protected:
+ virtual ~Base() {}
+
+private:
+ oslInterlockedCount m_count;
+};
+
+class Impl1: public Interface1, private Base {
+public:
+ virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const & type) override
+ {
+ if (type == cppu::UnoType<css::uno::XInterface>::get()) {
+ css::uno::Reference< css::uno::XInterface > ref(
+ static_cast< css::uno::XInterface * >(this));
+ return css::uno::Any(&ref, type);
+ }
+ if (type == cppu::UnoType<Interface1>::get()) {
+ css::uno::Reference< Interface1 > ref(this);
+ return css::uno::Any(&ref, type);
+ }
+ return css::uno::Any();
+ }
+
+ virtual void SAL_CALL acquire() noexcept override {
+ Base::acquire();
+ }
+
+ virtual void SAL_CALL release() noexcept override {
+ Base::release();
+ }
+};
+
+class Impl2: public Interface2a, public Interface3, private Base {
+public:
+ virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const & type) override
+ {
+ if (type == cppu::UnoType<css::uno::XInterface>::get()) {
+ css::uno::Reference< css::uno::XInterface > ref(
+ static_cast< css::uno::XInterface * >(
+ static_cast< Interface2a * >(this)));
+ return css::uno::Any(&ref, type);
+ }
+ if (type == cppu::UnoType<Interface2>::get()) {
+ css::uno::Reference< Interface2 > ref(this);
+ return css::uno::Any(&ref, type);
+ }
+ if (type == cppu::UnoType<Interface2a>::get()) {
+ css::uno::Reference< Interface2a > ref(this);
+ return css::uno::Any(&ref, type);
+ }
+ if (type == cppu::UnoType<Interface3>::get()) {
+ css::uno::Reference< Interface3 > ref(this);
+ return css::uno::Any(&ref, type);
+ }
+ return css::uno::Any();
+ }
+
+ virtual void SAL_CALL acquire() noexcept override {
+ Base::acquire();
+ }
+
+ virtual void SAL_CALL release() noexcept override {
+ Base::release();
+ }
+};
+
+class Impl2b: public Interface2b, private Base {
+public:
+ virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const & type) override
+ {
+ if (type == cppu::UnoType<css::uno::XInterface>::get()) {
+ css::uno::Reference< css::uno::XInterface > ref(
+ static_cast< css::uno::XInterface * >(
+ static_cast< Interface2a * >(this)));
+ return css::uno::Any(&ref, type);
+ }
+ if (type == cppu::UnoType<Interface2>::get()) {
+ css::uno::Reference< Interface2 > ref(this);
+ return css::uno::Any(&ref, type);
+ }
+ if (type == cppu::UnoType<Interface2a>::get()) {
+ css::uno::Reference< Interface2a > ref(this);
+ return css::uno::Any(&ref, type);
+ }
+ if (type == cppu::UnoType<Interface2b>::get()) {
+ css::uno::Reference< Interface2b > ref(this);
+ return css::uno::Any(&ref, type);
+ }
+ return css::uno::Any();
+ }
+
+ virtual void SAL_CALL acquire() noexcept override {
+ Base::acquire();
+ }
+
+ virtual void SAL_CALL release() noexcept override {
+ Base::release();
+ }
+};
+
+class Test: public CppUnit::TestFixture {
+public:
+ void testVoid();
+ void testBoolean();
+ void testByte();
+ void testShort();
+ void testUnsignedShort();
+ void testLong();
+ void testUnsignedLong();
+ void testHyper();
+ void testUnsignedHyper();
+ void testFloat();
+ void testDouble();
+ void testChar();
+ void testString();
+ void testType();
+ void testSequence();
+ void testEnum();
+ void testStruct();
+ void testPoly();
+ void testException();
+ void testInterface();
+ void testNull();
+
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testVoid);
+ CPPUNIT_TEST(testBoolean);
+ CPPUNIT_TEST(testByte);
+ CPPUNIT_TEST(testShort);
+ CPPUNIT_TEST(testUnsignedShort);
+ CPPUNIT_TEST(testLong);
+ CPPUNIT_TEST(testUnsignedLong);
+ CPPUNIT_TEST(testHyper);
+ CPPUNIT_TEST(testUnsignedHyper);
+ CPPUNIT_TEST(testFloat);
+ CPPUNIT_TEST(testDouble);
+ CPPUNIT_TEST(testChar);
+ CPPUNIT_TEST(testString);
+ CPPUNIT_TEST(testType);
+ CPPUNIT_TEST(testSequence);
+ CPPUNIT_TEST(testEnum);
+ CPPUNIT_TEST(testStruct);
+ CPPUNIT_TEST(testPoly);
+ CPPUNIT_TEST(testException);
+ CPPUNIT_TEST(testInterface);
+ CPPUNIT_TEST(testNull);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void Test::testVoid() {
+ css::uno::Any a;
+ CPPUNIT_ASSERT(bool(a.getValueType() == cppu::UnoType<void>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(2), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(2), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(2), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(2), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(2), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(2), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", 2.0f, b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 2.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>", sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+}
+
+void Test::testBoolean() {
+ css::uno::Any a(false);
+ CPPUNIT_ASSERT(bool(a.getValueType() == cppu::UnoType<bool>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", (a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", !b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", (a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(2), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(2), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(2), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(2), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(2), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(2), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", 2.0f, b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 2.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+}
+
+void Test::testByte() {
+ css::uno::Any a(static_cast< sal_Int8 >(1));
+ CPPUNIT_ASSERT(bool(a.getValueType() == cppu::UnoType<sal_Int8>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(1), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(1), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(1), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(1), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(1), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(1), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(1), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", float(1), b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 1.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+}
+
+void Test::testShort() {
+ css::uno::Any a(static_cast< sal_Int16 >(1));
+ CPPUNIT_ASSERT(bool(a.getValueType() == cppu::UnoType<sal_Int16>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(1), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(1), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(1), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(1), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(1), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(1), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", float(1), b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 1.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+}
+
+void Test::testUnsignedShort() {
+ sal_uInt16 n = 1;
+ css::uno::Any a(&n, cppu::UnoType<cppu::UnoUnsignedShortType>::get());
+ CPPUNIT_ASSERT(
+ bool(a.getValueType() == cppu::UnoType<cppu::UnoUnsignedShortType>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(1), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(1), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(1), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(1), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(1), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(1), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", float(1), b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 1.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+}
+
+void Test::testLong() {
+ css::uno::Any a(static_cast< sal_Int32 >(1));
+ CPPUNIT_ASSERT(bool(a.getValueType() == cppu::UnoType<sal_Int32>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(2), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(2), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(1), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(1), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(1), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(1), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", float(2), b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 1.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+}
+
+void Test::testUnsignedLong() {
+ css::uno::Any a(static_cast< sal_uInt32 >(1));
+ CPPUNIT_ASSERT(bool(a.getValueType() == cppu::UnoType<sal_uInt32>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(2), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(2), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(1), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(1), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(1), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(1), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", float(2), b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 1.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+}
+
+void Test::testHyper() {
+ css::uno::Any a(static_cast< sal_Int64 >(1));
+ CPPUNIT_ASSERT(bool(a.getValueType() == cppu::UnoType<sal_Int64>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(2), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(2), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(2), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(2), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(1), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(1), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", float(2), b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 2.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+}
+
+void Test::testUnsignedHyper() {
+ css::uno::Any a(static_cast< sal_uInt64 >(1));
+ CPPUNIT_ASSERT(bool(a.getValueType() == cppu::UnoType<sal_uInt64>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(2), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(2), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(2), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(2), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(1), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(1), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", float(2), b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 2.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+}
+
+void Test::testFloat() {
+ css::uno::Any a(1.f);
+ CPPUNIT_ASSERT(bool(a.getValueType() == cppu::UnoType<float>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(2), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(2), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(2), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(2), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(2), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(2), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", float(1), b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 1.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+}
+
+void Test::testDouble() {
+ css::uno::Any a(1.);
+ CPPUNIT_ASSERT(bool(a.getValueType() == cppu::UnoType<double>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(2), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(2), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(2), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(2), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(2), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(2), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", float(2), b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 1.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+}
+
+void Test::testChar() {
+ sal_Unicode c = '1';
+ css::uno::Any a(&c, cppu::UnoType<cppu::UnoCharType>::get());
+ CPPUNIT_ASSERT(bool(a.getValueType() == cppu::UnoType<cppu::UnoCharType>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(2), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(2), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(2), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(2), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(2), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(2), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", float(2), b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 2.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'1', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+}
+
+void Test::testString() {
+ css::uno::Any a(OUString("1"));
+ CPPUNIT_ASSERT(bool(a.getValueType() == cppu::UnoType<OUString>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(2), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(2), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(2), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(2), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(2), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(2), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", float(2), b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 2.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", (a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("1"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+}
+
+void Test::testType() {
+ css::uno::Any a(cppu::UnoType<sal_Int32>::get());
+ CPPUNIT_ASSERT(bool(a.getValueType() == cppu::UnoType<css::uno::Type>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(2), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(2), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(2), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(2), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(2), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(2), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", float(2), b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 2.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type", cppu::UnoType<sal_Int32>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+}
+
+void Test::testSequence() {
+ sal_Int32 n = 1;
+ css::uno::Any a(css::uno::Sequence< sal_Int32 >(&n, 1));
+ CPPUNIT_ASSERT(
+ bool(a.getValueType()
+ == cppu::UnoType<css::uno::Sequence<sal_Int32>>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(2), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(2), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(2), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(2), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(2), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(2), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", float(2), b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 2.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ css::uno::Sequence< sal_Int32 > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<sal_Int32>",
+ (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<sal_Int32>",
+ sal_Int32(1), b.getLength());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<sal_Int32>",
+ sal_Int32(1), b[0]);
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+ {
+ // The two default-constructed sequences both refer to the same static cppu::g_emptySeq
+ css::uno::Sequence<sal_Int32> aEmptyIntSequence;
+ css::uno::Sequence<OUString> aEmptyStringSequence;
+ a <<= aEmptyStringSequence;
+ CPPUNIT_ASSERT(!(a >>= aEmptyIntSequence));
+ }
+}
+
+void Test::testEnum() {
+ css::uno::Any a(Enum2_M1);
+ CPPUNIT_ASSERT(bool(a.getValueType() == cppu::UnoType<Enum2>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(2), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(2), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(2), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(2), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(2), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(2), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", float(2), b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 2.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Enum2 b = Enum2_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum2", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum2", Enum2_M1, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+}
+
+void Test::testStruct() {
+ css::uno::Any a(Struct2a(1, 3));
+ CPPUNIT_ASSERT(bool(a.getValueType() == cppu::UnoType<Struct2a>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(2), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(2), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(2), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(2), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(2), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(2), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", float(2), b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 2.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Struct2 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct2", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct2", sal_Int32(1), b.member);
+ }
+ {
+ Struct2a b(2, 2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "Struct2a", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "Struct2a", sal_Int32(1), b.member);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "Struct2a", sal_Int32(3), b.member2);
+ }
+ {
+ Struct2b b(2, 2, 2);
+ CPPUNIT_ASSERT_MESSAGE("Struct2b", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct2b", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+}
+
+void Test::testPoly() {
+ css::uno::Any a;
+ a <<= Poly< css::uno::Sequence< ::sal_Unicode > >();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "type name", OUString("Poly<[]char>"), a.getValueType().getTypeName() );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "constructor",
+ css::uno::Any(Poly< css::uno::Sequence< ::sal_Unicode > >()), a);
+}
+
+void Test::testException() {
+ css::uno::Any a(
+ Exception2a(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 1,
+ 3));
+ CPPUNIT_ASSERT(bool(a.getValueType() == cppu::UnoType<Exception2a>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(2), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(2), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(2), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(2), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(2), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(2), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", float(2), b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 2.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ Exception2 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception2", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception2", sal_Int32(1), b.member);
+ }
+ {
+ Exception2a b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2,
+ 2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "Exception2a", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "Exception2a", sal_Int32(1), b.member);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "Exception2a", sal_Int32(3), b.member2);
+ }
+ {
+ Exception2b b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2,
+ 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception2b", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception2b", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+}
+
+void Test::testInterface() {
+ css::uno::Reference< Interface2a > i2(new Impl2);
+ css::uno::Any a(i2);
+ CPPUNIT_ASSERT(bool(a.getValueType() == cppu::UnoType<Interface2a>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(2), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(2), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(2), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(2), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(2), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(2), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", float(2), b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 2.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > i(new Impl1);
+ css::uno::Reference< Interface1 > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface1", i, b);
+ }
+ {
+ css::uno::Reference< Interface2 > b(new Impl2);
+ CPPUNIT_ASSERT_MESSAGE("Interface2", (a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("Interface2", b.operator ==(i2));
+ }
+ {
+ css::uno::Reference< Interface2a > b(new Impl2);
+ CPPUNIT_ASSERT_MESSAGE("Interface2a", (a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface2a", i2, b);
+ }
+ {
+ css::uno::Reference< Interface2b > i(new Impl2b);
+ css::uno::Reference< Interface2b > b(i);
+ CPPUNIT_ASSERT_MESSAGE("Interface2b", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Interface2b", i, b);
+ }
+ {
+ css::uno::Reference< Interface3 > b(new Impl2);
+ CPPUNIT_ASSERT_MESSAGE("Interface3", (a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("Interface3", b.operator ==(i2));
+ }
+}
+
+void Test::testNull() {
+ css::uno::Any a { css::uno::Reference< Interface2a >() };
+ CPPUNIT_ASSERT(bool(a.getValueType() == cppu::UnoType<Interface2a>::get()));
+ {
+ bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("bool", b);
+ }
+ {
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b = true;
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", !(a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("sal_Bool", b);
+ }
+ {
+ sal_Int8 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int8", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int8", sal_Int8(2), b);
+ }
+ {
+ sal_Int16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int16", sal_Int16(2), b);
+ }
+ {
+ sal_uInt16 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt16", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt16", sal_uInt16(2), b);
+ }
+ {
+ sal_Int32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int32", sal_Int32(2), b);
+ }
+ {
+ sal_uInt32 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt32", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt32", sal_uInt32(2), b);
+ }
+ {
+ sal_Int64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_Int64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Int64", sal_Int64(2), b);
+ }
+ {
+ sal_uInt64 b = 2;
+ CPPUNIT_ASSERT_MESSAGE("sal_uInt64", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_uInt64", sal_uInt64(2), b);
+ }
+ {
+ float b = 2;
+ CPPUNIT_ASSERT_MESSAGE("float", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("float", float(2), b);
+ }
+ {
+ double b = 2;
+ CPPUNIT_ASSERT_MESSAGE("double", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("double", 2.0, b);
+ }
+ {
+ sal_Unicode b = '2';
+ CPPUNIT_ASSERT_MESSAGE("sal_Unicode", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("sal_Unicode", u'2', b);
+ }
+ {
+ OUString b("2");
+ CPPUNIT_ASSERT_MESSAGE( "OUString", !(a >>= b) );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "OUString", OUString("2"), b );
+ }
+ {
+ css::uno::Type b(cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Type",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Type",
+ cppu::UnoType<OUString>::get(), b);
+ }
+ {
+ css::uno::Sequence< OUString > b(2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "css::uno::Sequence<OUString>",
+ sal_Int32(2), b.getLength());
+ }
+ {
+ Enum1 b = Enum1_M2;
+ CPPUNIT_ASSERT_MESSAGE("Enum1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Enum1", Enum1_M2, b);
+ }
+ {
+ Struct1 b(2);
+ CPPUNIT_ASSERT_MESSAGE("Struct1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Struct1", sal_Int32(2), b.member);
+ }
+ {
+ Exception1 b(
+ OUString(), css::uno::Reference< css::uno::XInterface >(), 2);
+ CPPUNIT_ASSERT_MESSAGE("Exception1", !(a >>= b));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Exception1", sal_Int32(2), b.member);
+ }
+ {
+ css::uno::Reference< Interface1 > b(new Impl1);
+ CPPUNIT_ASSERT_MESSAGE(
+ "Interface1", (a >>= b));
+ CPPUNIT_ASSERT_MESSAGE(
+ "Interface1", !b.is());
+ }
+ {
+ css::uno::Reference< Interface2 > b(new Impl2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "Interface2", (a >>= b));
+ CPPUNIT_ASSERT_MESSAGE(
+ "Interface2", !b.is());
+ }
+ {
+ css::uno::Reference< Interface2a > b(new Impl2);
+ CPPUNIT_ASSERT_MESSAGE("Interface2a", (a >>= b));
+ CPPUNIT_ASSERT_MESSAGE("Interface2a", !b.is());
+ }
+ {
+ css::uno::Reference< Interface2b > b(new Impl2b);
+ CPPUNIT_ASSERT_MESSAGE(
+ "Interface2b", (a >>= b));
+ CPPUNIT_ASSERT_MESSAGE(
+ "Interface2b", !b.is());
+ }
+ {
+ css::uno::Reference< Interface3 > b(new Impl2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "Interface3", (a >>= b));
+ CPPUNIT_ASSERT_MESSAGE(
+ "Interface3", !b.is());
+ }
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/qa/test_recursion.cxx b/cppu/qa/test_recursion.cxx
new file mode 100644
index 000000000..40aee4c30
--- /dev/null
+++ b/cppu/qa/test_recursion.cxx
@@ -0,0 +1,53 @@
+/* -*- 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/TestSuite.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/TestCase.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <Rec.hpp>
+
+namespace
+{
+
+class Test: public CppUnit::TestFixture {
+
+public:
+ void testRecursion();
+
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testRecursion);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void Test::testRecursion() {
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int32 >(0), Rec().x.getLength());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/qa/test_reference.cxx b/cppu/qa/test_reference.cxx
new file mode 100644
index 000000000..698a8d5fe
--- /dev/null
+++ b/cppu/qa/test_reference.cxx
@@ -0,0 +1,203 @@
+/* -*- 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/TestFixture.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <Interface1.hpp>
+
+namespace
+{
+
+using ::com::sun::star::uno::Type;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::RuntimeException;
+using ::com::sun::star::uno::UNO_SET_THROW;
+
+class Foo: public Interface1
+{
+public:
+ Foo()
+ :m_refCount(0)
+ {
+ }
+
+ Foo(const Foo&) = delete;
+ const Foo& operator=(const Foo&) = delete;
+
+ virtual Any SAL_CALL queryInterface(const Type & _type) override
+ {
+ if (_type == cppu::UnoType<XInterface>::get())
+ {
+ return css::uno::Any(css::uno::Reference<css::uno::XInterface>(
+ this));
+ }
+ if (_type == cppu::UnoType<Interface1>::get())
+ {
+ return css::uno::Any(css::uno::Reference<Interface1>(this));
+ }
+
+ return Any();
+ }
+
+ virtual void SAL_CALL acquire() noexcept override
+ {
+ osl_atomic_increment( &m_refCount );
+ }
+
+ virtual void SAL_CALL release() noexcept override
+ {
+ if ( 0 == osl_atomic_decrement( &m_refCount ) )
+ delete this;
+ }
+
+protected:
+ virtual ~Foo()
+ {
+ }
+
+private:
+ oslInterlockedCount m_refCount;
+};
+
+// Check that the up-casting Reference conversion constructor catches the
+// intended cases:
+
+struct Base1: public css::uno::XInterface {
+ virtual ~Base1() = delete;
+ static ::css::uno::Type const & static_type(void * = nullptr) // loplugin:refcounting
+ { return ::cppu::UnoType<Base1>::get(); }
+};
+struct Base2: public Base1 {
+ virtual ~Base2() override = delete;
+};
+struct Base3: public Base1 { virtual ~Base3() override = delete; };
+struct Derived: public Base2, public Base3 {
+ virtual ~Derived() override = delete;
+};
+
+// The special case using the conversion operator instead:
+css::uno::Reference< css::uno::XInterface > testUpcast1(
+ css::uno::Reference< Derived > const & ref)
+{
+ Base1::static_type(); // prevent loplugin:unreffun firing
+ return ref;
+}
+
+// The normal up-cast case:
+css::uno::Reference< Base1 > testUpcast2(
+ css::uno::Reference< Base2 > const & ref)
+{ return ref; }
+
+// Commenting this in should cause a compiler error due to an ambiguous up-cast:
+/*
+css::uno::Reference< Base1 > testFailingUpcast3(
+ css::uno::Reference< Derived > const & ref)
+{ return ref; }
+*/
+
+// Commenting this in should cause a compiler error due to a down-cast:
+/*
+css::uno::Reference< Base2 > testFailingUpcast4(
+ css::uno::Reference< Base1 > const & ref)
+{ return ref; }
+*/
+
+// Commenting this in should cause a compiler error due to a down-cast:
+/*
+css::uno::Reference< Base1 > testFailingUpcast5(
+ css::uno::Reference< css::uno::XInterface > const & ref)
+{ return ref; }
+*/
+
+class Test: public ::CppUnit::TestFixture
+{
+
+public:
+ void testUnoSetThrow();
+ void testUpcastCompilation();
+
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testUnoSetThrow);
+ CPPUNIT_TEST(testUpcastCompilation);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void Test::testUnoSetThrow()
+{
+ Reference< Interface1 > xNull;
+ Reference< Interface1 > xFoo( new Foo );
+
+ // ctor taking Reference< interface_type >
+ bool bCaughtException = false;
+ try { Reference< Interface1 > x( xNull, UNO_SET_THROW ); } catch( const RuntimeException& ) { bCaughtException = true; }
+ CPPUNIT_ASSERT_EQUAL( true, bCaughtException );
+
+ bCaughtException = false;
+ try { Reference< Interface1 > x( xFoo, UNO_SET_THROW ); } catch( const RuntimeException& ) { bCaughtException = true; }
+ CPPUNIT_ASSERT_EQUAL( false, bCaughtException );
+
+ // ctor taking interface_type*
+ bCaughtException = false;
+ try { Reference< Interface1 > x( xNull.get(), UNO_SET_THROW ); } catch( const RuntimeException& ) { bCaughtException = true; }
+ CPPUNIT_ASSERT_EQUAL( true, bCaughtException );
+
+ bCaughtException = false;
+ try { Reference< Interface1 > x( xFoo.get(), UNO_SET_THROW ); } catch( const RuntimeException& ) { bCaughtException = true; }
+ CPPUNIT_ASSERT_EQUAL( false, bCaughtException );
+
+ Reference< Interface1 > x;
+ // "set" taking Reference< interface_type >
+ bCaughtException = false;
+ try { x.set( xNull, UNO_SET_THROW ); } catch( const RuntimeException& ) { bCaughtException = true; }
+ CPPUNIT_ASSERT_EQUAL( true, bCaughtException );
+
+ bCaughtException = false;
+ try { x.set( xFoo, UNO_SET_THROW ); } catch( const RuntimeException& ) { bCaughtException = true; }
+ CPPUNIT_ASSERT_EQUAL( false, bCaughtException );
+
+ // "set" taking interface_type*
+ bCaughtException = false;
+ try { x.set( xNull.get(), UNO_SET_THROW ); } catch( const RuntimeException& ) { bCaughtException = true; }
+ CPPUNIT_ASSERT_EQUAL( true, bCaughtException );
+
+ bCaughtException = false;
+ try { x.set( xFoo.get(), UNO_SET_THROW ); } catch( const RuntimeException& ) { bCaughtException = true; }
+ CPPUNIT_ASSERT_EQUAL( false, bCaughtException );
+}
+
+// Include a dummy test calling those functions, to avoid warnings about those
+// functions being unused:
+void Test::testUpcastCompilation()
+{
+ testUpcast1(css::uno::Reference< Derived >());
+ testUpcast2(css::uno::Reference< Base2 >());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+} // namespace
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/qa/test_unotype.cxx b/cppu/qa/test_unotype.cxx
new file mode 100644
index 000000000..829676a14
--- /dev/null
+++ b/cppu/qa/test_unotype.cxx
@@ -0,0 +1,558 @@
+/* -*- 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/TestFixture.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <typeinfo>
+
+#include <com/sun/star/beans/Optional.hpp>
+#include <com/sun/star/beans/PropertyChangeEvent.hpp>
+#include <com/sun/star/lang/EventObject.hpp>
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Type.hxx>
+#include <com/sun/star/uno/TypeClass.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <cppu/unotype.hxx>
+#include <rtl/ustring.hxx>
+
+namespace com::sun::star::uno {
+ class Any;
+}
+
+namespace com::sun::star::uno { template <class interface_type> class Reference; }
+
+namespace {
+
+struct DerivedStruct1: css::lang::EventObject {};
+
+struct DerivedStruct2: css::beans::PropertyChangeEvent {};
+
+struct DerivedException1: css::uno::Exception {};
+
+struct DerivedException2: css::uno::RuntimeException {};
+
+struct DerivedInterface1: css::uno::XInterface {
+private:
+ ~DerivedInterface1() {}
+ // avoid warnings about virtual members and non-virtual dtor
+
+public:
+ static void dummy(DerivedInterface1 * p)
+ { p->DerivedInterface1::~DerivedInterface1(); }
+ // ...and avoid warnings about unused ~DerivedInterface1 (see below)
+};
+
+struct DerivedInterface2: css::uno::XComponentContext {
+private:
+ ~DerivedInterface2() {}
+ // avoid warnings about virtual members and non-virtual dtor
+
+public:
+ static void dummy(DerivedInterface2 * p)
+ { p->DerivedInterface2::~DerivedInterface2(); }
+ // ...and avoid warnings about unused ~DerivedInterface2 (see below)
+};
+
+class Test: public CppUnit::TestFixture {
+public:
+ void testUnoType();
+
+ void testGetTypeFavourUnsigned();
+
+ void testGetTypeFavourChar();
+
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testUnoType);
+ CPPUNIT_TEST(testGetTypeFavourUnsigned);
+ CPPUNIT_TEST(testGetTypeFavourChar);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void Test::testUnoType() {
+ // Avoid warnings about unused ~DerivedInterface1/2 (see above):
+ if ((false)) {
+ DerivedInterface1::dummy(nullptr);
+ DerivedInterface2::dummy(nullptr);
+ }
+
+ css::uno::Type t;
+ t = cppu::UnoType<cppu::UnoVoidType>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_VOID, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("void"), t.getTypeName());
+ CPPUNIT_ASSERT(bool(cppu::UnoType<void>::get() == t));
+ t = cppu::UnoType<bool>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_BOOLEAN, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("boolean"), t.getTypeName());
+ CPPUNIT_ASSERT(bool(cppu::UnoType<sal_Bool>::get() == t));
+ t = cppu::UnoType<sal_Int8>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_BYTE, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("byte"), t.getTypeName());
+ t = cppu::UnoType<sal_Int16>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_SHORT, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("short"), t.getTypeName());
+ t = cppu::UnoType<cppu::UnoUnsignedShortType>::get();
+ CPPUNIT_ASSERT_EQUAL(
+ css::uno::TypeClass_UNSIGNED_SHORT, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("unsigned short"), t.getTypeName());
+ t = cppu::UnoType<sal_Int32>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_LONG, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("long"), t.getTypeName());
+ t = cppu::UnoType<sal_uInt32>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_UNSIGNED_LONG, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("unsigned long"), t.getTypeName());
+ t = cppu::UnoType<sal_Int64>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_HYPER, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("hyper"), t.getTypeName());
+ t = cppu::UnoType<sal_uInt64>::get();
+ CPPUNIT_ASSERT_EQUAL(
+ css::uno::TypeClass_UNSIGNED_HYPER, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("unsigned hyper"), t.getTypeName());
+ t = cppu::UnoType<float>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_FLOAT, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("float"), t.getTypeName());
+ t = cppu::UnoType<double>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_DOUBLE, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("double"), t.getTypeName());
+ t = cppu::UnoType<cppu::UnoCharType>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_CHAR, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("char"), t.getTypeName());
+ t = cppu::UnoType<OUString>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_STRING, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("string"), t.getTypeName());
+ t = cppu::UnoType<css::uno::Type>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_TYPE, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("type"), t.getTypeName());
+ t = cppu::UnoType<css::uno::Any>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_ANY, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("any"), t.getTypeName());
+ t = cppu::UnoType<cppu::UnoSequenceType<sal_Int8>>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_SEQUENCE, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("[]byte"), t.getTypeName());
+ CPPUNIT_ASSERT(bool(cppu::UnoType<css::uno::Sequence<sal_Int8>>::get() == t));
+ t = cppu::UnoType<cppu::UnoSequenceType<cppu::UnoUnsignedShortType>>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_SEQUENCE, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("[]unsigned short"), t.getTypeName());
+ t = cppu::UnoType<cppu::UnoSequenceType<cppu::UnoCharType>>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_SEQUENCE, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("[]char"), t.getTypeName());
+ t = cppu::UnoType<
+ cppu::UnoSequenceType<cppu::UnoSequenceType<sal_Int8>>>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_SEQUENCE, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("[][]byte"), t.getTypeName());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::UnoType<css::uno::Sequence<css::uno::Sequence<sal_Int8>>>::get(),
+ t);
+ t = cppu::UnoType<
+ cppu::UnoSequenceType<
+ cppu::UnoSequenceType<cppu::UnoUnsignedShortType>>>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_SEQUENCE, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("[][]unsigned short"), t.getTypeName());
+ t = cppu::UnoType<
+ cppu::UnoSequenceType<cppu::UnoSequenceType<cppu::UnoCharType>>>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_SEQUENCE, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(OUString("[][]char"), t.getTypeName());
+ t = cppu::UnoType<css::uno::TypeClass>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_ENUM, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("com.sun.star.uno.TypeClass"), t.getTypeName());
+ t = cppu::UnoType<css::lang::EventObject>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_STRUCT, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("com.sun.star.lang.EventObject"), t.getTypeName());
+ CPPUNIT_ASSERT_EQUAL(cppu::UnoType<DerivedStruct1>::get(), t);
+ t = cppu::UnoType<css::beans::PropertyChangeEvent>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_STRUCT, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("com.sun.star.beans.PropertyChangeEvent"), t.getTypeName());
+ CPPUNIT_ASSERT_EQUAL(cppu::UnoType<DerivedStruct2>::get(), t);
+ t = cppu::UnoType<css::beans::Optional<sal_Int8>>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_STRUCT, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("com.sun.star.beans.Optional<byte>"), t.getTypeName());
+ t = cppu::UnoType<css::uno::Exception>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_EXCEPTION, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("com.sun.star.uno.Exception"), t.getTypeName());
+ CPPUNIT_ASSERT_EQUAL(cppu::UnoType<DerivedException1>::get(), t);
+ t = cppu::UnoType<css::uno::RuntimeException>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_EXCEPTION, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("com.sun.star.uno.RuntimeException"), t.getTypeName());
+ CPPUNIT_ASSERT_EQUAL(cppu::UnoType<DerivedException2>::get(), t);
+ t = cppu::UnoType<css::uno::XInterface>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_INTERFACE, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("com.sun.star.uno.XInterface"), t.getTypeName());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::UnoType<css::uno::Reference<css::uno::XInterface>>::get(), t);
+ CPPUNIT_ASSERT_EQUAL(cppu::UnoType<DerivedInterface1>::get(), t);
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::UnoType<css::uno::Reference<DerivedInterface1>>::get(), t);
+ t = cppu::UnoType<css::uno::XComponentContext>::get();
+ CPPUNIT_ASSERT_EQUAL(css::uno::TypeClass_INTERFACE, t.getTypeClass());
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("com.sun.star.uno.XComponentContext"), t.getTypeName());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::UnoType<css::uno::Reference<css::uno::XComponentContext>>::get(),
+ t);
+ CPPUNIT_ASSERT_EQUAL(cppu::UnoType<DerivedInterface2>::get(), t);
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::UnoType<css::uno::Reference<DerivedInterface2>>::get(), t);
+}
+
+void Test::testGetTypeFavourUnsigned() {
+ CPPUNIT_ASSERT(typeid(sal_Unicode) != typeid(sal_uInt16));
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<cppu::UnoVoidType *>(nullptr)),
+ cppu::UnoType<cppu::UnoVoidType>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<bool *>(nullptr)),
+ cppu::UnoType<bool>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<sal_Bool *>(nullptr)),
+ cppu::UnoType<bool>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<sal_Int8 *>(nullptr)),
+ cppu::UnoType<sal_Int8>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<sal_Int16 *>(nullptr)),
+ cppu::UnoType<sal_Int16>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<cppu::UnoUnsignedShortType *>(nullptr)),
+ cppu::UnoType<cppu::UnoUnsignedShortType>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<sal_uInt16 *>(nullptr)),
+ cppu::UnoType<cppu::UnoUnsignedShortType>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<sal_Int32 *>(nullptr)),
+ cppu::UnoType<sal_Int32>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<sal_uInt32 *>(nullptr)),
+ cppu::UnoType<sal_uInt32>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<sal_Int64 *>(nullptr)),
+ cppu::UnoType<sal_Int64>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<sal_uInt64 *>(nullptr)),
+ cppu::UnoType<sal_uInt64>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<float *>(nullptr)),
+ cppu::UnoType<float>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<double *>(nullptr)),
+ cppu::UnoType<double>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<cppu::UnoCharType *>(nullptr)),
+ cppu::UnoType<cppu::UnoCharType>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<sal_Unicode *>(nullptr)),
+ cppu::UnoType<cppu::UnoCharType>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<OUString *>(nullptr)),
+ cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<css::uno::Type *>(nullptr)),
+ cppu::UnoType<css::uno::Type>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<css::uno::Any *>(nullptr)),
+ cppu::UnoType<css::uno::Any>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<
+ cppu::UnoSequenceType<cppu::UnoUnsignedShortType> *>(nullptr)),
+ cppu::UnoType<
+ cppu::UnoSequenceType<cppu::UnoUnsignedShortType>>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<css::uno::Sequence<sal_uInt16> *>(nullptr)),
+ cppu::UnoType<
+ cppu::UnoSequenceType<cppu::UnoUnsignedShortType>>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<
+ cppu::UnoSequenceType<
+ cppu::UnoSequenceType<
+ cppu::UnoUnsignedShortType>> *>(nullptr)),
+ cppu::UnoType<
+ cppu::UnoSequenceType<
+ cppu::UnoSequenceType<cppu::UnoUnsignedShortType>>>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<
+ css::uno::Sequence<css::uno::Sequence<sal_uInt16>> *>(nullptr)),
+ cppu::UnoType<
+ cppu::UnoSequenceType<
+ cppu::UnoSequenceType<cppu::UnoUnsignedShortType>>>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<css::uno::Sequence<sal_Unicode> *>(nullptr)),
+ cppu::UnoType<cppu::UnoSequenceType<cppu::UnoCharType>>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<
+ css::uno::Sequence<
+ css::uno::Sequence<sal_Unicode>> *>(nullptr)),
+ cppu::UnoType<
+ cppu::UnoSequenceType<
+ cppu::UnoSequenceType<cppu::UnoCharType>>>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<css::uno::TypeClass *>(nullptr)),
+ cppu::UnoType<css::uno::TypeClass>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<css::lang::EventObject *>(nullptr)),
+ cppu::UnoType<css::lang::EventObject>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<DerivedStruct1 *>(nullptr)),
+ cppu::UnoType<css::lang::EventObject>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<css::beans::PropertyChangeEvent *>(nullptr)),
+ cppu::UnoType<css::beans::PropertyChangeEvent>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<DerivedStruct2 *>(nullptr)),
+ cppu::UnoType<css::beans::PropertyChangeEvent>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<css::beans::Optional<sal_Int8> *>(nullptr)),
+ cppu::UnoType<css::beans::Optional<sal_Int8>>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<css::uno::Exception *>(nullptr)),
+ cppu::UnoType<css::uno::Exception>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<DerivedException1 *>(nullptr)),
+ cppu::UnoType<css::uno::Exception>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<css::uno::RuntimeException *>(nullptr)),
+ cppu::UnoType<css::uno::RuntimeException>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<DerivedException2 *>(nullptr)),
+ cppu::UnoType<css::uno::RuntimeException>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<css::uno::XInterface *>(nullptr)),
+ cppu::UnoType<css::uno::XInterface>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<css::uno::Reference<css::uno::XInterface> *>(nullptr)),
+ cppu::UnoType<css::uno::XInterface>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<DerivedInterface1 *>(nullptr)),
+ cppu::UnoType<css::uno::XInterface>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<css::uno::Reference<DerivedInterface1> *>(nullptr)),
+ cppu::UnoType<css::uno::XInterface>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<css::uno::XComponentContext *>(nullptr)),
+ cppu::UnoType<css::uno::XComponentContext>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<
+ css::uno::Reference<css::uno::XComponentContext> *>(nullptr)),
+ cppu::UnoType<css::uno::XComponentContext>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(static_cast<DerivedInterface2 *>(nullptr)),
+ cppu::UnoType<css::uno::XComponentContext>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourUnsigned(
+ static_cast<css::uno::Reference<DerivedInterface2> *>(nullptr)),
+ cppu::UnoType<css::uno::XComponentContext>::get());
+}
+
+void Test::testGetTypeFavourChar() {
+ CPPUNIT_ASSERT(typeid(sal_Unicode) != typeid(sal_uInt16));
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<cppu::UnoVoidType *>(nullptr)),
+ cppu::UnoType<cppu::UnoVoidType>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<bool *>(nullptr)),
+ cppu::UnoType<bool>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<sal_Bool *>(nullptr)),
+ cppu::UnoType<bool>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<sal_Int8 *>(nullptr)),
+ cppu::UnoType<sal_Int8>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<sal_Int16 *>(nullptr)),
+ cppu::UnoType<sal_Int16>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(
+ static_cast<cppu::UnoUnsignedShortType *>(nullptr)),
+ cppu::UnoType<cppu::UnoUnsignedShortType>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<sal_uInt16 *>(nullptr)),
+ cppu::UnoType<cppu::UnoUnsignedShortType>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<sal_Int32 *>(nullptr)),
+ cppu::UnoType<sal_Int32>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<sal_uInt32 *>(nullptr)),
+ cppu::UnoType<sal_uInt32>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<sal_Int64 *>(nullptr)),
+ cppu::UnoType<sal_Int64>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<sal_uInt64 *>(nullptr)),
+ cppu::UnoType<sal_uInt64>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<float *>(nullptr)),
+ cppu::UnoType<float>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<double *>(nullptr)),
+ cppu::UnoType<double>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<cppu::UnoCharType *>(nullptr)),
+ cppu::UnoType<cppu::UnoCharType>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<sal_Unicode *>(nullptr)),
+ cppu::UnoType<cppu::UnoCharType>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<OUString *>(nullptr)),
+ cppu::UnoType<OUString>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<css::uno::Type *>(nullptr)),
+ cppu::UnoType<css::uno::Type>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<css::uno::Any *>(nullptr)),
+ cppu::UnoType<css::uno::Any>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(
+ static_cast<
+ cppu::UnoSequenceType<cppu::UnoUnsignedShortType> *>(nullptr)),
+ cppu::UnoType<
+ cppu::UnoSequenceType<cppu::UnoUnsignedShortType>>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(
+ static_cast<css::uno::Sequence<sal_uInt16> *>(nullptr)),
+ cppu::UnoType<
+ cppu::UnoSequenceType<cppu::UnoUnsignedShortType>>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(
+ static_cast<
+ cppu::UnoSequenceType<
+ cppu::UnoSequenceType<
+ cppu::UnoUnsignedShortType>> *>(nullptr)),
+ cppu::UnoType<
+ cppu::UnoSequenceType<
+ cppu::UnoSequenceType<cppu::UnoUnsignedShortType>>>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(
+ static_cast<
+ css::uno::Sequence<css::uno::Sequence<sal_uInt16>> *>(nullptr)),
+ cppu::UnoType<
+ cppu::UnoSequenceType<
+ cppu::UnoSequenceType<cppu::UnoUnsignedShortType>>>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(
+ static_cast<css::uno::Sequence<sal_Unicode> *>(nullptr)),
+ cppu::UnoType<cppu::UnoSequenceType<cppu::UnoCharType>>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(
+ static_cast<
+ css::uno::Sequence<
+ css::uno::Sequence<sal_Unicode>> *>(nullptr)),
+ cppu::UnoType<
+ cppu::UnoSequenceType<
+ cppu::UnoSequenceType<cppu::UnoCharType>>>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<css::uno::TypeClass *>(nullptr)),
+ cppu::UnoType<css::uno::TypeClass>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<css::lang::EventObject *>(nullptr)),
+ cppu::UnoType<css::lang::EventObject>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<DerivedStruct1 *>(nullptr)),
+ cppu::UnoType<css::lang::EventObject>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(
+ static_cast<css::beans::PropertyChangeEvent *>(nullptr)),
+ cppu::UnoType<css::beans::PropertyChangeEvent>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<DerivedStruct2 *>(nullptr)),
+ cppu::UnoType<css::beans::PropertyChangeEvent>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(
+ static_cast<css::beans::Optional<sal_Int8> *>(nullptr)),
+ cppu::UnoType<css::beans::Optional<sal_Int8>>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<css::uno::Exception *>(nullptr)),
+ cppu::UnoType<css::uno::Exception>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<DerivedException1 *>(nullptr)),
+ cppu::UnoType<css::uno::Exception>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(
+ static_cast<css::uno::RuntimeException *>(nullptr)),
+ cppu::UnoType<css::uno::RuntimeException>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<DerivedException2 *>(nullptr)),
+ cppu::UnoType<css::uno::RuntimeException>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<css::uno::XInterface *>(nullptr)),
+ cppu::UnoType<css::uno::XInterface>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(
+ static_cast<css::uno::Reference<css::uno::XInterface> *>(nullptr)),
+ cppu::UnoType<css::uno::XInterface>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<DerivedInterface1 *>(nullptr)),
+ cppu::UnoType<css::uno::XInterface>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(
+ static_cast<css::uno::Reference<DerivedInterface1> *>(nullptr)),
+ cppu::UnoType<css::uno::XInterface>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(
+ static_cast<css::uno::XComponentContext *>(nullptr)),
+ cppu::UnoType<css::uno::XComponentContext>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(
+ static_cast<
+ css::uno::Reference<css::uno::XComponentContext> *>(nullptr)),
+ cppu::UnoType<css::uno::XComponentContext>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(static_cast<DerivedInterface2 *>(nullptr)),
+ cppu::UnoType<css::uno::XComponentContext>::get());
+ CPPUNIT_ASSERT_EQUAL(
+ cppu::getTypeFavourChar(
+ static_cast<css::uno::Reference<DerivedInterface2> *>(nullptr)),
+ cppu::UnoType<css::uno::XComponentContext>::get());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/qa/typelib.cxx b/cppu/qa/typelib.cxx
new file mode 100644
index 000000000..227e5731c
--- /dev/null
+++ b/cppu/qa/typelib.cxx
@@ -0,0 +1,293 @@
+/* -*- 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/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/io/XTextInputStream.hpp>
+#include <com/sun/star/lang/EventObject.hpp>
+#include <com/sun/star/script/FinishReason.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Type.hxx>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <cppu/unotype.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+#include <typelib/typedescription.h>
+#include <typelib/typedescription.hxx>
+
+// Test that typelib_typedescription_register as called from typelib_typedescription_complete
+// returns a correct typelib_TypeDescription and keeps pointers from the original
+// typelib_TypeDescription intact (see tdf#115399 "Data race in typelib_typedescription_register").
+// This code uses sufficiently "obscure" types in typelib_static_*_type_init to make it unlikely
+// that they are already instantiated and registered with the type description manager, which might
+// cause inconsistencies.
+
+namespace
+{
+class Test : public CppUnit::TestFixture
+{
+public:
+ void testEnum()
+ {
+ typelib_TypeDescriptionReference* ref = nullptr;
+ typelib_static_enum_type_init(&ref, "com.sun.star.script.MemberType", 0);
+ CPPUNIT_ASSERT(ref != nullptr);
+ typelib_TypeDescription* td = ref->pType;
+ CPPUNIT_ASSERT(td != nullptr);
+ typelib_typedescription_acquire(td);
+ CPPUNIT_ASSERT(!td->bComplete);
+ auto t = reinterpret_cast<typelib_EnumTypeDescription*>(td);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), t->nDefaultEnumValue);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), t->nEnumValues);
+ CPPUNIT_ASSERT(t->ppEnumNames == nullptr);
+ CPPUNIT_ASSERT(t->pEnumValues == nullptr);
+ CPPUNIT_ASSERT(typelib_typedescription_complete(&td));
+ CPPUNIT_ASSERT(td != nullptr);
+ CPPUNIT_ASSERT(td->bComplete);
+ t = reinterpret_cast<typelib_EnumTypeDescription*>(td);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), t->nDefaultEnumValue);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), t->nEnumValues);
+ CPPUNIT_ASSERT(t->ppEnumNames != nullptr);
+ CPPUNIT_ASSERT_EQUAL(OUString("METHOD"), OUString::unacquired(&t->ppEnumNames[0]));
+ CPPUNIT_ASSERT_EQUAL(OUString("PROPERTY"), OUString::unacquired(&t->ppEnumNames[1]));
+ CPPUNIT_ASSERT_EQUAL(OUString("UNKNOWN"), OUString::unacquired(&t->ppEnumNames[2]));
+ CPPUNIT_ASSERT(t->pEnumValues != nullptr);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), t->pEnumValues[0]);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), t->pEnumValues[1]);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), t->pEnumValues[2]);
+ typelib_typedescription_release(td);
+ typelib_typedescriptionreference_release(ref);
+ }
+
+ void testStruct()
+ {
+ auto const t0 = cppu::UnoType<css::lang::EventObject>::get();
+ auto const t1 = cppu::UnoType<css::script::FinishReason>::get();
+ auto const t2 = cppu::UnoType<OUString>::get();
+ auto const t3 = cppu::UnoType<css::uno::Any>::get();
+ typelib_TypeDescriptionReference* ref = nullptr;
+ typelib_TypeDescriptionReference* members[3]
+ = { t1.getTypeLibType(), t2.getTypeLibType(), t3.getTypeLibType() };
+ typelib_static_struct_type_init(&ref, "com.sun.star.script.FinishEngineEvent",
+ t0.getTypeLibType(), 3, members, nullptr);
+ CPPUNIT_ASSERT(ref != nullptr);
+ typelib_TypeDescription* td = ref->pType;
+ CPPUNIT_ASSERT(td != nullptr);
+ typelib_typedescription_acquire(td);
+ CPPUNIT_ASSERT(!td->bComplete);
+ auto t = reinterpret_cast<typelib_StructTypeDescription*>(td);
+ CPPUNIT_ASSERT(css::uno::TypeDescription(&t->aBase.pBaseTypeDescription->aBase).equals(t0));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), t->aBase.nMembers);
+ auto const offsets = t->aBase.pMemberOffsets;
+ CPPUNIT_ASSERT(offsets != nullptr);
+ auto const typerefs = t->aBase.ppTypeRefs;
+ CPPUNIT_ASSERT(typerefs != nullptr);
+ CPPUNIT_ASSERT_EQUAL(t1, css::uno::Type(typerefs[0]));
+ CPPUNIT_ASSERT_EQUAL(t2, css::uno::Type(typerefs[1]));
+ CPPUNIT_ASSERT_EQUAL(t3, css::uno::Type(typerefs[2]));
+ CPPUNIT_ASSERT(t->aBase.ppMemberNames == nullptr);
+ CPPUNIT_ASSERT(t->pParameterizedTypes == nullptr);
+ CPPUNIT_ASSERT(typelib_typedescription_complete(&td));
+ CPPUNIT_ASSERT(td != nullptr);
+ CPPUNIT_ASSERT(td->bComplete);
+ t = reinterpret_cast<typelib_StructTypeDescription*>(td);
+ CPPUNIT_ASSERT(css::uno::TypeDescription(&t->aBase.pBaseTypeDescription->aBase).equals(t0));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), t->aBase.nMembers);
+ CPPUNIT_ASSERT(t->aBase.pMemberOffsets != nullptr);
+ CPPUNIT_ASSERT(t->aBase.ppTypeRefs != nullptr);
+ CPPUNIT_ASSERT_EQUAL(t1, css::uno::Type(t->aBase.ppTypeRefs[0]));
+ CPPUNIT_ASSERT_EQUAL(t2, css::uno::Type(t->aBase.ppTypeRefs[1]));
+ CPPUNIT_ASSERT_EQUAL(t3, css::uno::Type(t->aBase.ppTypeRefs[2]));
+ CPPUNIT_ASSERT(t->aBase.ppMemberNames != nullptr);
+ CPPUNIT_ASSERT_EQUAL(OUString("Finish"), OUString::unacquired(&t->aBase.ppMemberNames[0]));
+ CPPUNIT_ASSERT_EQUAL(OUString("ErrorMessage"),
+ OUString::unacquired(&t->aBase.ppMemberNames[1]));
+ CPPUNIT_ASSERT_EQUAL(OUString("Return"), OUString::unacquired(&t->aBase.ppMemberNames[2]));
+ CPPUNIT_ASSERT(t->pParameterizedTypes == nullptr);
+ // `offsets` and `typerefs` must still be valid:
+ CPPUNIT_ASSERT_EQUAL(t->aBase.pMemberOffsets[0], offsets[0]);
+ CPPUNIT_ASSERT_EQUAL(t->aBase.pMemberOffsets[1], offsets[1]);
+ CPPUNIT_ASSERT_EQUAL(t->aBase.pMemberOffsets[2], offsets[2]);
+ CPPUNIT_ASSERT_EQUAL(css::uno::Type(t->aBase.ppTypeRefs[0]), css::uno::Type(typerefs[0]));
+ CPPUNIT_ASSERT_EQUAL(css::uno::Type(t->aBase.ppTypeRefs[1]), css::uno::Type(typerefs[1]));
+ CPPUNIT_ASSERT_EQUAL(css::uno::Type(t->aBase.ppTypeRefs[2]), css::uno::Type(typerefs[2]));
+ typelib_typedescription_release(td);
+ typelib_typedescriptionreference_release(ref);
+ }
+
+ void testPolyStruct()
+ {
+ auto const t1 = cppu::UnoType<bool>::get();
+ auto const t2 = cppu::UnoType<sal_Int32>::get();
+ typelib_TypeDescriptionReference* ref = nullptr;
+ typelib_TypeDescriptionReference* members[2] = { t1.getTypeLibType(), t2.getTypeLibType() };
+ sal_Bool const param[2] = { false, true };
+ typelib_static_struct_type_init(&ref, "com.sun.star.beans.Optional<long>", nullptr, 2,
+ members, param);
+ CPPUNIT_ASSERT(ref != nullptr);
+ typelib_TypeDescription* td = ref->pType;
+ CPPUNIT_ASSERT(td != nullptr);
+ typelib_typedescription_acquire(td);
+ CPPUNIT_ASSERT(!td->bComplete);
+ auto t = reinterpret_cast<typelib_StructTypeDescription*>(td);
+ CPPUNIT_ASSERT(t->aBase.pBaseTypeDescription == nullptr);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), t->aBase.nMembers);
+ auto const offsets = t->aBase.pMemberOffsets;
+ CPPUNIT_ASSERT(offsets != nullptr);
+ auto const typerefs = t->aBase.ppTypeRefs;
+ CPPUNIT_ASSERT(typerefs != nullptr);
+ CPPUNIT_ASSERT_EQUAL(t1, css::uno::Type(typerefs[0]));
+ CPPUNIT_ASSERT_EQUAL(t2, css::uno::Type(typerefs[1]));
+ CPPUNIT_ASSERT(t->aBase.ppMemberNames == nullptr);
+ CPPUNIT_ASSERT(t->pParameterizedTypes != nullptr);
+ CPPUNIT_ASSERT_EQUAL(param[0], t->pParameterizedTypes[0]);
+ CPPUNIT_ASSERT_EQUAL(param[1], t->pParameterizedTypes[1]);
+ CPPUNIT_ASSERT(typelib_typedescription_complete(&td));
+ CPPUNIT_ASSERT(td != nullptr);
+ CPPUNIT_ASSERT(td->bComplete);
+ t = reinterpret_cast<typelib_StructTypeDescription*>(td);
+ CPPUNIT_ASSERT(t->aBase.pBaseTypeDescription == nullptr);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), t->aBase.nMembers);
+ CPPUNIT_ASSERT(t->aBase.pMemberOffsets != nullptr);
+ CPPUNIT_ASSERT(t->aBase.ppTypeRefs != nullptr);
+ CPPUNIT_ASSERT_EQUAL(t1, css::uno::Type(t->aBase.ppTypeRefs[0]));
+ CPPUNIT_ASSERT_EQUAL(t2, css::uno::Type(t->aBase.ppTypeRefs[1]));
+ CPPUNIT_ASSERT(t->aBase.ppMemberNames != nullptr);
+ CPPUNIT_ASSERT_EQUAL(OUString("IsPresent"),
+ OUString::unacquired(&t->aBase.ppMemberNames[0]));
+ CPPUNIT_ASSERT_EQUAL(OUString("Value"), OUString::unacquired(&t->aBase.ppMemberNames[1]));
+ CPPUNIT_ASSERT(t->pParameterizedTypes != nullptr);
+ CPPUNIT_ASSERT_EQUAL(param[0], t->pParameterizedTypes[0]);
+ CPPUNIT_ASSERT_EQUAL(param[1], t->pParameterizedTypes[1]);
+ // `offsets` and `typerefs` must still be valid:
+ CPPUNIT_ASSERT_EQUAL(t->aBase.pMemberOffsets[0], offsets[0]);
+ CPPUNIT_ASSERT_EQUAL(t->aBase.pMemberOffsets[1], offsets[1]);
+ CPPUNIT_ASSERT_EQUAL(css::uno::Type(t->aBase.ppTypeRefs[0]), css::uno::Type(typerefs[0]));
+ CPPUNIT_ASSERT_EQUAL(css::uno::Type(t->aBase.ppTypeRefs[1]), css::uno::Type(typerefs[1]));
+ typelib_typedescription_release(td);
+ typelib_typedescriptionreference_release(ref);
+ }
+
+ void testInterface()
+ {
+ auto const t0 = cppu::UnoType<css::uno::XInterface>::get();
+ typelib_TypeDescriptionReference* ref = nullptr;
+ typelib_TypeDescriptionReference* bases[1] = { t0.getTypeLibType() };
+ typelib_static_mi_interface_type_init(&ref, "com.sun.star.script.XTypeConverter", 1, bases);
+ CPPUNIT_ASSERT(ref != nullptr);
+ typelib_TypeDescription* td = ref->pType;
+ CPPUNIT_ASSERT(td != nullptr);
+ typelib_typedescription_acquire(td);
+ CPPUNIT_ASSERT(!td->bComplete);
+ auto t = reinterpret_cast<typelib_InterfaceTypeDescription*>(td);
+ CPPUNIT_ASSERT(css::uno::TypeDescription(&t->pBaseTypeDescription->aBase).equals(t0));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), t->nMembers);
+ CPPUNIT_ASSERT(t->ppMembers == nullptr);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), t->nAllMembers);
+ CPPUNIT_ASSERT(t->ppAllMembers == nullptr);
+ CPPUNIT_ASSERT(t->pMapMemberIndexToFunctionIndex == nullptr);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), t->nMapFunctionIndexToMemberIndex);
+ CPPUNIT_ASSERT(t->pMapFunctionIndexToMemberIndex == nullptr);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), t->nBaseTypes);
+ auto const basetypes = t->ppBaseTypes;
+ CPPUNIT_ASSERT(basetypes != nullptr);
+ CPPUNIT_ASSERT(css::uno::TypeDescription(&basetypes[0]->aBase).equals(t0));
+ CPPUNIT_ASSERT(typelib_typedescription_complete(&td));
+ CPPUNIT_ASSERT(td != nullptr);
+ CPPUNIT_ASSERT(td->bComplete);
+ t = reinterpret_cast<typelib_InterfaceTypeDescription*>(td);
+ CPPUNIT_ASSERT(css::uno::TypeDescription(&t->pBaseTypeDescription->aBase).equals(t0));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), t->nMembers);
+ CPPUNIT_ASSERT(t->ppMembers != nullptr);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), t->nAllMembers);
+ CPPUNIT_ASSERT(t->ppAllMembers != nullptr);
+ CPPUNIT_ASSERT(t->pMapMemberIndexToFunctionIndex != nullptr);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), t->nMapFunctionIndexToMemberIndex);
+ CPPUNIT_ASSERT(t->pMapFunctionIndexToMemberIndex != nullptr);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), t->nBaseTypes);
+ CPPUNIT_ASSERT(t->ppBaseTypes != nullptr);
+ CPPUNIT_ASSERT(css::uno::TypeDescription(&t->ppBaseTypes[0]->aBase).equals(t0));
+ // `basetypes` must still be valid:
+ CPPUNIT_ASSERT(
+ css::uno::TypeDescription(&basetypes[0]->aBase).equals(&t->ppBaseTypes[0]->aBase));
+ typelib_typedescription_release(td);
+ typelib_typedescriptionreference_release(ref);
+ }
+
+ void testMultiInterface()
+ {
+ auto const t1 = cppu::UnoType<css::io::XTextInputStream>::get();
+ auto const t2 = cppu::UnoType<css::io::XActiveDataSink>::get();
+ typelib_TypeDescriptionReference* ref = nullptr;
+ typelib_TypeDescriptionReference* bases[2] = { t1.getTypeLibType(), t2.getTypeLibType() };
+ typelib_static_mi_interface_type_init(&ref, "com.sun.star.io.XTextInputStream2", 2, bases);
+ CPPUNIT_ASSERT(ref != nullptr);
+ typelib_TypeDescription* td = ref->pType;
+ CPPUNIT_ASSERT(td != nullptr);
+ typelib_typedescription_acquire(td);
+ CPPUNIT_ASSERT(!td->bComplete);
+ auto t = reinterpret_cast<typelib_InterfaceTypeDescription*>(td);
+ CPPUNIT_ASSERT(css::uno::TypeDescription(&t->pBaseTypeDescription->aBase).equals(t1));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), t->nMembers);
+ CPPUNIT_ASSERT(t->ppMembers == nullptr);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), t->nAllMembers);
+ CPPUNIT_ASSERT(t->ppAllMembers == nullptr);
+ CPPUNIT_ASSERT(t->pMapMemberIndexToFunctionIndex == nullptr);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), t->nMapFunctionIndexToMemberIndex);
+ CPPUNIT_ASSERT(t->pMapFunctionIndexToMemberIndex == nullptr);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), t->nBaseTypes);
+ auto const basetypes = t->ppBaseTypes;
+ CPPUNIT_ASSERT(basetypes != nullptr);
+ CPPUNIT_ASSERT(css::uno::TypeDescription(&basetypes[0]->aBase).equals(t1));
+ CPPUNIT_ASSERT(css::uno::TypeDescription(&basetypes[1]->aBase).equals(t2));
+ CPPUNIT_ASSERT(typelib_typedescription_complete(&td));
+ CPPUNIT_ASSERT(td != nullptr);
+ CPPUNIT_ASSERT(td->bComplete);
+ t = reinterpret_cast<typelib_InterfaceTypeDescription*>(td);
+ CPPUNIT_ASSERT(css::uno::TypeDescription(&t->pBaseTypeDescription->aBase).equals(t1));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), t->nMembers);
+ CPPUNIT_ASSERT(t->ppMembers == nullptr);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(14), t->nAllMembers);
+ CPPUNIT_ASSERT(t->ppAllMembers != nullptr);
+ CPPUNIT_ASSERT(t->pMapMemberIndexToFunctionIndex != nullptr);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(14), t->nMapFunctionIndexToMemberIndex);
+ CPPUNIT_ASSERT(t->pMapFunctionIndexToMemberIndex != nullptr);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), t->nBaseTypes);
+ CPPUNIT_ASSERT(t->ppBaseTypes != nullptr);
+ CPPUNIT_ASSERT(css::uno::TypeDescription(&t->ppBaseTypes[0]->aBase).equals(t1));
+ CPPUNIT_ASSERT(css::uno::TypeDescription(&t->ppBaseTypes[1]->aBase).equals(t2));
+ // `basetypes` must still be valid:
+ CPPUNIT_ASSERT(
+ css::uno::TypeDescription(&basetypes[0]->aBase).equals(&t->ppBaseTypes[0]->aBase));
+ CPPUNIT_ASSERT(
+ css::uno::TypeDescription(&basetypes[1]->aBase).equals(&t->ppBaseTypes[1]->aBase));
+ typelib_typedescription_release(td);
+ typelib_typedescriptionreference_release(ref);
+ }
+
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testEnum);
+ CPPUNIT_TEST(testStruct);
+ CPPUNIT_TEST(testPolyStruct);
+ CPPUNIT_TEST(testInterface);
+ CPPUNIT_TEST(testMultiInterface);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/cppu/qa/types.idl b/cppu/qa/types.idl
new file mode 100644
index 000000000..a17b035e0
--- /dev/null
+++ b/cppu/qa/types.idl
@@ -0,0 +1,57 @@
+/* -*- 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/uno/Exception.idl>
+#include <com/sun/star/uno/XInterface.idl>
+
+enum Enum1 { M0, M1, M2 };
+
+enum Enum2 { M0, M1, M2 };
+
+struct Struct1 { long member; };
+
+struct Struct2 { long member; };
+
+struct Struct2a: Struct2 { long member2; };
+
+struct Struct2b: Struct2a { long member3; };
+
+struct Poly< T > { long member; };
+
+struct Rec { sequence< Rec > x; };
+
+exception Exception1: com::sun::star::uno::Exception { long member; };
+
+exception Exception2: com::sun::star::uno::Exception { long member; };
+
+exception Exception2a: Exception2 { long member2; };
+
+exception Exception2b: Exception2a {};
+
+interface Interface1 {};
+
+interface Interface2 {};
+
+interface Interface2a: Interface2 {};
+
+interface Interface2b: Interface2a {};
+
+interface Interface3 {};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/AffineBridge/AffineBridge.cxx b/cppu/source/AffineBridge/AffineBridge.cxx
new file mode 100644
index 000000000..3e2b01df1
--- /dev/null
+++ b/cppu/source/AffineBridge/AffineBridge.cxx
@@ -0,0 +1,360 @@
+/* -*- 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/thread.hxx>
+#include <osl/conditn.hxx>
+#include <osl/mutex.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+
+#include <cppu/Enterable.hxx>
+#include <cppu/helper/purpenv/Environment.hxx>
+#include <cppu/helper/purpenv/Mapping.hxx>
+#include <memory>
+
+namespace {
+
+class InnerThread;
+class OuterThread;
+
+class AffineBridge : public cppu::Enterable
+{
+public:
+ enum Msg
+ {
+ CB_DONE,
+ CB_FPOINTER
+ };
+
+ Msg m_message;
+ uno_EnvCallee * m_pCallee;
+ va_list * m_pParam;
+
+ osl::Mutex m_innerMutex;
+ oslThreadIdentifier m_innerThreadId;
+ std::unique_ptr<InnerThread> m_pInnerThread;
+ osl::Condition m_innerCondition;
+ sal_Int32 m_enterCount;
+
+ osl::Mutex m_outerMutex;
+ oslThreadIdentifier m_outerThreadId;
+ osl::Condition m_outerCondition;
+ std::unique_ptr<OuterThread> m_pOuterThread;
+
+ explicit AffineBridge();
+ virtual ~AffineBridge() override;
+
+ virtual void v_callInto_v(uno_EnvCallee * pCallee, va_list * pParam) override;
+ virtual void v_callOut_v (uno_EnvCallee * pCallee, va_list * pParam) override;
+
+ virtual void v_enter() override;
+ virtual void v_leave() override;
+
+ virtual bool v_isValid(OUString * pReason) override;
+
+ void innerDispatch();
+ void outerDispatch(bool loop);
+};
+
+class InnerThread : public osl::Thread
+{
+ virtual void SAL_CALL run() override;
+
+ AffineBridge * m_pAffineBridge;
+
+public:
+ explicit InnerThread(AffineBridge * threadEnvironment)
+ : m_pAffineBridge(threadEnvironment)
+ {
+ create();
+ }
+};
+
+}
+
+void InnerThread::run()
+{
+ osl_setThreadName("UNO AffineBridge InnerThread");
+
+ m_pAffineBridge->enter();
+ m_pAffineBridge->innerDispatch();
+ m_pAffineBridge->leave();
+}
+
+namespace {
+
+class OuterThread : public osl::Thread
+{
+ virtual void SAL_CALL run() override;
+
+ AffineBridge * m_pAffineBridge;
+
+public:
+ explicit OuterThread(AffineBridge * threadEnvironment);
+};
+
+}
+
+OuterThread::OuterThread(AffineBridge * threadEnvironment)
+ : m_pAffineBridge(threadEnvironment)
+{
+ create();
+}
+
+void OuterThread::run()
+{
+ osl_setThreadName("UNO AffineBridge OuterThread");
+
+ osl::MutexGuard guard(m_pAffineBridge->m_outerMutex);
+
+ m_pAffineBridge->m_outerThreadId = getIdentifier();
+ m_pAffineBridge->outerDispatch(false);
+ m_pAffineBridge->m_outerThreadId = 0;
+
+ m_pAffineBridge->m_pOuterThread = nullptr;
+ m_pAffineBridge = nullptr;
+}
+
+
+AffineBridge::AffineBridge()
+ : m_message (CB_DONE),
+ m_pCallee (nullptr),
+ m_pParam (nullptr),
+ m_innerThreadId(0),
+ m_enterCount (0),
+ m_outerThreadId(0)
+{
+ SAL_INFO("cppu.affinebridge", "LIFE: AffineBridge::AffineBridge(uno_Environment * pEnv) -> " << this);
+}
+
+AffineBridge::~AffineBridge()
+{
+ SAL_INFO("cppu.affinebridge", "LIFE: AffineBridge::~AffineBridge() -> " << this);
+
+ if (m_pInnerThread && osl::Thread::getCurrentIdentifier() != m_innerThreadId)
+ {
+ m_message = CB_DONE;
+ m_innerCondition.set();
+
+ m_pInnerThread->join();
+ }
+
+ m_pInnerThread.reset();
+
+ if (m_pOuterThread)
+ {
+ m_pOuterThread->join();
+ }
+}
+
+
+void AffineBridge::outerDispatch(bool loop)
+{
+ OSL_ASSERT(m_outerThreadId == osl::Thread::getCurrentIdentifier());
+ OSL_ASSERT(m_innerThreadId != m_outerThreadId);
+
+ Msg mm;
+
+ do
+ {
+ // FIXME: created outer thread must not wait
+ // in case of no message
+ // note: no message can happen in case newly created
+ // outer thread acquire outerMutex after a real outer
+ // thread enters outerDispatch!
+ m_outerCondition.wait();
+ m_outerCondition.reset();
+
+ mm = m_message;
+
+ switch(mm)
+ {
+ case CB_DONE:
+ break;
+
+ case CB_FPOINTER:
+ {
+ m_pCallee(m_pParam);
+
+ m_message = CB_DONE;
+ m_innerCondition.set();
+ break;
+ }
+ default:
+ abort();
+ }
+ }
+ while(mm != CB_DONE && loop);
+}
+
+void AffineBridge::innerDispatch()
+{
+ OSL_ASSERT(m_innerThreadId == osl::Thread::getCurrentIdentifier());
+ OSL_ASSERT(m_innerThreadId != m_outerThreadId);
+
+ Msg mm;
+
+ do
+ {
+ m_innerCondition.wait();
+ m_innerCondition.reset();
+
+ mm = m_message;
+
+ switch(mm)
+ {
+ case CB_DONE:
+ break;
+
+ case CB_FPOINTER:
+ {
+ m_pCallee(m_pParam);
+
+ m_message = CB_DONE;
+ m_outerCondition.set();
+ break;
+ }
+ default:
+ abort();
+ }
+ }
+ while(mm != CB_DONE);
+}
+
+void AffineBridge::v_callInto_v(uno_EnvCallee * pCallee, va_list * pParam)
+{
+ osl::MutexGuard guard(m_outerMutex); // only one thread at a time can call into
+
+ if (m_innerThreadId == 0) // no inner thread yet
+ {
+ m_pInnerThread.reset(new InnerThread(this));
+ }
+
+ bool bResetId = false;
+ if (!m_outerThreadId)
+ {
+ m_outerThreadId = osl::Thread::getCurrentIdentifier();
+ bResetId = true;
+ }
+
+ m_message = CB_FPOINTER;
+ m_pCallee = pCallee;
+ m_pParam = pParam;
+ m_innerCondition.set();
+
+ outerDispatch(true);
+
+ if (bResetId)
+ m_outerThreadId = 0;
+}
+
+void AffineBridge::v_callOut_v(uno_EnvCallee * pCallee, va_list * pParam)
+{
+ OSL_ASSERT(m_innerThreadId);
+
+ osl::MutexGuard guard(m_innerMutex);
+
+ if (m_outerThreadId == 0) // no outer thread yet
+ {
+ osl::MutexGuard guard_m_outerMutex(m_outerMutex);
+
+ if (m_outerThreadId == 0)
+ {
+ if (m_pOuterThread)
+ {
+ m_pOuterThread->join();
+ }
+
+ m_pOuterThread.reset(new OuterThread(this));
+ }
+ }
+
+ m_message = CB_FPOINTER;
+ m_pCallee = pCallee;
+ m_pParam = pParam;
+ m_outerCondition.set();
+
+ innerDispatch();
+}
+
+void AffineBridge::v_enter()
+{
+ m_innerMutex.acquire();
+
+ if (!m_enterCount)
+ m_innerThreadId = osl::Thread::getCurrentIdentifier();
+
+ OSL_ASSERT(m_innerThreadId == osl::Thread::getCurrentIdentifier());
+
+ ++ m_enterCount;
+}
+
+void AffineBridge::v_leave()
+{
+ OSL_ASSERT(m_innerThreadId == osl::Thread::getCurrentIdentifier());
+
+ -- m_enterCount;
+ if (!m_enterCount)
+ m_innerThreadId = 0;
+
+ m_innerMutex.release();
+}
+
+bool AffineBridge::v_isValid(OUString * pReason)
+{
+ bool result = m_enterCount > 0;
+ if (!result)
+ *pReason = "not entered";
+
+ else
+ {
+ result = m_innerThreadId == osl::Thread::getCurrentIdentifier();
+
+ if (!result)
+ *pReason = "wrong thread";
+ }
+
+ if (result)
+ *pReason = "OK";
+
+ return result;
+}
+
+#ifdef DISABLE_DYNLOADING
+
+#define uno_initEnvironment affine_uno_uno_initEnvironment
+#define uno_ext_getMapping affine_uno_uno_ext_getMapping
+
+#endif
+
+extern "C" void SAL_DLLPUBLIC_EXPORT uno_initEnvironment(uno_Environment * pEnv)
+ SAL_THROW_EXTERN_C()
+{
+ cppu::helper::purpenv::Environment_initWithEnterable(pEnv, new AffineBridge());
+}
+
+extern "C" void SAL_DLLPUBLIC_EXPORT uno_ext_getMapping(uno_Mapping ** ppMapping,
+ uno_Environment * pFrom,
+ uno_Environment * pTo )
+{
+ cppu::helper::purpenv::createMapping(ppMapping, pFrom, pTo);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/LogBridge/LogBridge.cxx b/cppu/source/LogBridge/LogBridge.cxx
new file mode 100644
index 000000000..b93b43b64
--- /dev/null
+++ b/cppu/source/LogBridge/LogBridge.cxx
@@ -0,0 +1,262 @@
+/* -*- 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/mutex.hxx>
+#include <osl/thread.h>
+#include <osl/thread.hxx>
+#include <osl/diagnose.h>
+#include <cppu/Enterable.hxx>
+#include <cppu/helper/purpenv/Environment.hxx>
+#include <cppu/helper/purpenv/Mapping.hxx>
+#include <com/sun/star/uno/Type.hxx>
+#include <sal/log.hxx>
+
+namespace
+{
+class LogBridge : public cppu::Enterable
+{
+ osl::Mutex m_mutex;
+ sal_Int32 m_count;
+ oslThreadIdentifier m_threadId;
+
+ virtual ~LogBridge() override;
+
+public:
+ explicit LogBridge();
+
+ virtual void v_callInto_v(uno_EnvCallee * pCallee, va_list * pParam) override;
+ virtual void v_callOut_v (uno_EnvCallee * pCallee, va_list * pParam) override;
+
+ virtual void v_enter() override;
+ virtual void v_leave() override;
+
+ virtual bool v_isValid(OUString * pReason) override;
+};
+
+LogBridge::LogBridge()
+ : m_count (0)
+ ,m_threadId(0)
+{
+}
+
+LogBridge::~LogBridge()
+{
+ OSL_ASSERT(m_count >= 0);
+}
+
+void LogBridge::v_callInto_v(uno_EnvCallee * pCallee, va_list * pParam)
+{
+ enter();
+ pCallee(pParam);
+ leave();
+}
+
+void LogBridge::v_callOut_v(uno_EnvCallee * pCallee, va_list * pParam)
+{
+ OSL_ASSERT(m_count > 0);
+
+ -- m_count;
+ pCallee(pParam);
+ ++ m_count;
+
+ if (!m_threadId)
+ m_threadId = osl::Thread::getCurrentIdentifier();
+}
+
+void LogBridge::v_enter()
+{
+ m_mutex.acquire();
+
+ OSL_ASSERT(m_count >= 0);
+
+ if (m_count == 0)
+ m_threadId = osl::Thread::getCurrentIdentifier();
+
+ ++ m_count;
+}
+
+void LogBridge::v_leave()
+{
+ OSL_ASSERT(m_count > 0);
+
+ -- m_count;
+ if (!m_count)
+ m_threadId = 0;
+
+
+ m_mutex.release();
+}
+
+bool LogBridge::v_isValid(OUString * pReason)
+{
+ bool result = m_count > 0;
+ if (!result)
+ {
+ *pReason = "not entered";
+ }
+ else
+ {
+ result = m_threadId == osl::Thread::getCurrentIdentifier();
+
+ if (!result)
+ *pReason = "wrong thread";
+ }
+
+ if (result)
+ *pReason = "OK";
+
+ return result;
+}
+
+ void traceValue(typelib_TypeDescriptionReference* _pTypeRef,void* pArg)
+ {
+ switch(_pTypeRef->eTypeClass)
+ {
+ case typelib_TypeClass_STRING:
+ SAL_INFO("cppu.log", "" << *static_cast< OUString*>(pArg));
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ SAL_INFO("cppu.log", "" << *static_cast<sal_Bool*>(pArg));
+ break;
+ case typelib_TypeClass_BYTE:
+ SAL_INFO("cppu.log", "" << *static_cast<sal_Int8*>(pArg));
+ break;
+ case typelib_TypeClass_CHAR:
+ SAL_INFO("cppu.log", "" << *static_cast<char*>(pArg));
+ break;
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ SAL_INFO("cppu.log", "" << *static_cast<sal_Int16*>(pArg));
+ break;
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ case typelib_TypeClass_ENUM:
+ SAL_INFO("cppu.log", "" << *static_cast<sal_Int32*>(pArg));
+ break;
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ SAL_INFO("cppu.log", "" << *static_cast<sal_Int64*>(pArg));
+ break;
+ case typelib_TypeClass_FLOAT:
+ SAL_INFO("cppu.log", "" << *static_cast<float*>(pArg));
+ break;
+ case typelib_TypeClass_DOUBLE:
+ SAL_INFO("cppu.log", "" << *static_cast<double*>(pArg));
+ break;
+ case typelib_TypeClass_TYPE:
+ SAL_INFO("cppu.log", "" << static_cast<css::uno::Type*>(pArg)->getTypeName());
+ break;
+ case typelib_TypeClass_ANY:
+ if ( static_cast<uno_Any*>(pArg)->pData )
+ traceValue(static_cast<uno_Any*>(pArg)->pType,static_cast<uno_Any*>(pArg)->pData);
+ else
+ SAL_INFO("cppu.log", "void");
+ break;
+ case typelib_TypeClass_EXCEPTION:
+ SAL_INFO("cppu.log", "exception");
+ break;
+ case typelib_TypeClass_INTERFACE:
+ SAL_INFO("cppu.log", "" << _pTypeRef->pTypeName << "0x" << std::hex << pArg);
+ break;
+ case typelib_TypeClass_VOID:
+ SAL_INFO("cppu.log", "void");
+ break;
+ default:
+ SAL_INFO("cppu.log", "0x" << std::hex << pArg);
+ break;
+ } // switch(pParams[i].pTypeRef->eTypeClass)
+ }
+}
+
+static void LogProbe(
+ bool pre,
+ SAL_UNUSED_PARAMETER void * /*pThis*/,
+ SAL_UNUSED_PARAMETER void * /*pContext*/,
+ typelib_TypeDescriptionReference * pReturnTypeRef,
+ typelib_MethodParameter * pParams,
+ sal_Int32 nParams,
+ typelib_TypeDescription const * pMemberType,
+ void * pReturn,
+ void * pArgs[],
+ uno_Any ** ppException )
+{
+ OString sTemp;
+ if ( pMemberType && pMemberType->pTypeName )
+ sTemp = OUStringToOString(
+ OUString::unacquired(&pMemberType->pTypeName),RTL_TEXTENCODING_ASCII_US);
+ if ( pre )
+ {
+ SAL_INFO("cppu.log", "{ LogBridge () " << sTemp );
+ if ( nParams )
+ {
+ SAL_INFO("cppu.log", "\n| : ( LogBridge ");
+ for(sal_Int32 i = 0;i < nParams;++i)
+ {
+ if ( i > 0 )
+ SAL_INFO("cppu.log", ",");
+ traceValue(pParams[i].pTypeRef,pArgs[i]);
+
+ }
+ SAL_INFO("cppu.log", ")");
+ } // if ( nParams )
+ SAL_INFO("cppu.log", "\n");
+ }
+ else if ( !pre )
+ {
+ SAL_INFO("cppu.log", "} LogBridge () " << sTemp);
+ if ( ppException && *ppException )
+ {
+ SAL_INFO("cppu.log", " exception occurred : ");
+ typelib_TypeDescription * pElementTypeDescr = nullptr;
+ TYPELIB_DANGER_GET( &pElementTypeDescr, (*ppException)->pType );
+ SAL_INFO("cppu.log", "" << pElementTypeDescr->pTypeName);
+ TYPELIB_DANGER_RELEASE( pElementTypeDescr );
+ }
+ else if ( pReturnTypeRef )
+ {
+ SAL_INFO("cppu.log", " return : ");
+ traceValue(pReturnTypeRef,pReturn);
+ } // if ( pReturn && pReturnTypeRef )
+
+ SAL_INFO("cppu.log", "\n");
+ }
+}
+
+#ifdef DISABLE_DYNLOADING
+
+#define uno_initEnvironment log_uno_uno_initEnvironment
+#define uno_ext_getMapping log_uno_uno_ext_getMapping
+
+#endif
+
+extern "C" void SAL_DLLPUBLIC_EXPORT uno_initEnvironment(uno_Environment * pEnv)
+ SAL_THROW_EXTERN_C()
+{
+ cppu::helper::purpenv::Environment_initWithEnterable(pEnv, new LogBridge());
+}
+
+extern "C" void SAL_DLLPUBLIC_EXPORT uno_ext_getMapping(uno_Mapping ** ppMapping,
+ uno_Environment * pFrom,
+ uno_Environment * pTo )
+{
+ cppu::helper::purpenv::createMapping(ppMapping, pFrom, pTo,LogProbe);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/UnsafeBridge/UnsafeBridge.cxx b/cppu/source/UnsafeBridge/UnsafeBridge.cxx
new file mode 100644
index 000000000..491a888c3
--- /dev/null
+++ b/cppu/source/UnsafeBridge/UnsafeBridge.cxx
@@ -0,0 +1,144 @@
+/* -*- 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/mutex.hxx>
+#include <osl/thread.h>
+#include <osl/thread.hxx>
+#include <sal/log.hxx>
+
+#include <cppu/Enterable.hxx>
+#include <cppu/helper/purpenv/Environment.hxx>
+#include <cppu/helper/purpenv/Mapping.hxx>
+
+namespace {
+
+class UnsafeBridge : public cppu::Enterable
+{
+ osl::Mutex m_mutex;
+ sal_Int32 m_count;
+ oslThreadIdentifier m_threadId;
+
+ virtual ~UnsafeBridge() override;
+
+public:
+ explicit UnsafeBridge();
+
+ virtual void v_callInto_v(uno_EnvCallee * pCallee, va_list * pParam) override;
+ virtual void v_callOut_v (uno_EnvCallee * pCallee, va_list * pParam) override;
+
+ virtual void v_enter() override;
+ virtual void v_leave() override;
+
+ virtual bool v_isValid(OUString * pReason) override;
+};
+
+}
+
+UnsafeBridge::UnsafeBridge()
+ : m_count (0),
+ m_threadId(0)
+{
+ SAL_INFO("cppu.unsafebridge", "LIFE: UnsafeBridge::UnsafeBridge(uno_Environment * pEnv) -> " << this);
+}
+
+UnsafeBridge::~UnsafeBridge()
+{
+ SAL_INFO("cppu.unsafebridge", "LIFE: UnsafeBridge::~UnsafeBridge() -> " << this);
+
+ SAL_WARN_IF(m_count < 0, "cppu.unsafebridge", "m_count is less than 0");
+}
+
+void UnsafeBridge::v_callInto_v(uno_EnvCallee * pCallee, va_list * pParam)
+{
+ enter();
+ pCallee(pParam);
+ leave();
+}
+
+void UnsafeBridge::v_callOut_v(uno_EnvCallee * pCallee, va_list * pParam)
+{
+ SAL_WARN_IF(m_count <= 0, "cppu.unsafebridge", "m_count is less than or equal to 0");
+
+ -- m_count;
+ pCallee(pParam);
+ ++ m_count;
+
+ if (!m_threadId)
+ m_threadId = osl::Thread::getCurrentIdentifier();
+}
+
+void UnsafeBridge::v_enter()
+{
+ m_mutex.acquire();
+
+ SAL_WARN_IF(m_count < 0, "cppu.unsafebridge", "m_count is less than 0");
+
+ if (m_count == 0)
+ m_threadId = osl::Thread::getCurrentIdentifier();
+
+ ++ m_count;
+}
+
+void UnsafeBridge::v_leave()
+{
+ SAL_WARN_IF(m_count <= 0, "cppu.unsafebridge", "m_count is less than or equal to 0");
+
+ -- m_count;
+ if (!m_count)
+ m_threadId = 0;
+
+
+ m_mutex.release();
+}
+
+bool UnsafeBridge::v_isValid(OUString * pReason)
+{
+ bool result = m_count > 0;
+ if (!result)
+ {
+ *pReason = "not entered";
+ }
+ else
+ {
+ result = m_threadId == osl::Thread::getCurrentIdentifier();
+
+ if (!result)
+ *pReason = "wrong thread";
+ }
+
+ if (result)
+ *pReason = "OK";
+
+ return result;
+}
+
+extern "C" void SAL_DLLPUBLIC_EXPORT uno_initEnvironment(uno_Environment * pEnv)
+ SAL_THROW_EXTERN_C()
+{
+ cppu::helper::purpenv::Environment_initWithEnterable(pEnv, new UnsafeBridge());
+}
+
+extern "C" void SAL_DLLPUBLIC_EXPORT uno_ext_getMapping(uno_Mapping ** ppMapping,
+ uno_Environment * pFrom,
+ uno_Environment * pTo )
+{
+ cppu::helper::purpenv::createMapping(ppMapping, pFrom, pTo);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/cppu/compat.cxx b/cppu/source/cppu/compat.cxx
new file mode 100644
index 000000000..06181e6ef
--- /dev/null
+++ b/cppu/source/cppu/compat.cxx
@@ -0,0 +1,47 @@
+/* -*- 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 <cstdlib>
+
+#include <typelib/typedescription.h>
+#include <rtl/ustring.h>
+#include <sal/types.h>
+
+// Stubs for removed functionality, to be killed when we bump sal SONAME
+
+extern "C" {
+
+SAL_DLLPUBLIC_EXPORT void SAL_CALL typelib_static_array_type_init(
+ typelib_TypeDescriptionReference **, typelib_TypeDescriptionReference *,
+ sal_Int32, ...) SAL_THROW_EXTERN_C()
+{
+ std::abort();
+}
+
+SAL_DLLPUBLIC_EXPORT void SAL_CALL typelib_typedescription_newArray(
+ typelib_TypeDescription **, typelib_TypeDescriptionReference *,
+ sal_Int32, sal_Int32 *) SAL_THROW_EXTERN_C()
+{
+ std::abort();
+}
+
+SAL_DLLPUBLIC_EXPORT void SAL_CALL typelib_typedescription_newUnion(
+ typelib_TypeDescription **, rtl_uString *,
+ typelib_TypeDescriptionReference *, sal_Int64,
+ typelib_TypeDescriptionReference *, sal_Int32, void *)
+ SAL_THROW_EXTERN_C()
+{
+ std::abort();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/cppu/cppu_opt.cxx b/cppu/source/cppu/cppu_opt.cxx
new file mode 100644
index 000000000..40f90de6e
--- /dev/null
+++ b/cppu/source/cppu/cppu_opt.cxx
@@ -0,0 +1,66 @@
+/* -*- 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/uno/Any.hxx>
+#include <typelib/typedescription.h>
+#include <uno/any2.h>
+#include <rtl/ustring.hxx>
+
+
+using namespace ::rtl;
+
+
+extern "C" rtl_uString * SAL_CALL cppu_unsatisfied_iquery_msg(
+ typelib_TypeDescriptionReference * pType )
+ SAL_THROW_EXTERN_C()
+{
+ OUString ret = "unsatisfied query for interface of type "
+ + OUString::unacquired( &pType->pTypeName ) + "!";
+ rtl_uString_acquire( ret.pData );
+ return ret.pData;
+}
+
+
+extern "C" rtl_uString * SAL_CALL cppu_unsatisfied_iset_msg(
+ typelib_TypeDescriptionReference * pType )
+ SAL_THROW_EXTERN_C()
+{
+ OUString ret = "invalid attempt to assign an empty interface of type "
+ + OUString::unacquired( &pType->pTypeName ) + "!";
+ rtl_uString_acquire( ret.pData );
+ return ret.pData;
+}
+
+
+extern "C" rtl_uString * SAL_CALL cppu_Any_extraction_failure_msg(
+ uno_Any const * pAny, typelib_TypeDescriptionReference * pType )
+ SAL_THROW_EXTERN_C()
+{
+ OUString ret = "Cannot extract an Any(" +
+ OUString::unacquired(&pAny->pType->pTypeName) +
+ ") to " +
+ OUString::unacquired(&pType->pTypeName) +
+ "!";
+ rtl_uString_acquire( ret.pData );
+ return ret.pData;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/helper/purpenv/Proxy.hxx b/cppu/source/helper/purpenv/Proxy.hxx
new file mode 100644
index 000000000..02c65a23a
--- /dev/null
+++ b/cppu/source/helper/purpenv/Proxy.hxx
@@ -0,0 +1,76 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <osl/interlck.h>
+
+#include <uno/environment.hxx>
+#include <uno/mapping.hxx>
+#include <uno/dispatcher.h>
+
+#include <cppu/helper/purpenv/Mapping.hxx>
+
+
+class Proxy : public uno_Interface
+{
+ oslInterlockedCount m_nRef;
+
+ css::uno::Environment m_from;
+ css::uno::Environment m_to;
+
+ css::uno::Mapping m_from_to;
+ css::uno::Mapping m_to_from;
+
+ // mapping information
+ uno_Interface * m_pUnoI; // wrapped interface
+ typelib_InterfaceTypeDescription * m_pTypeDescr;
+ OUString m_aOId;
+
+ cppu::helper::purpenv::ProbeFun * m_probeFun;
+ void * m_pProbeContext;
+
+public:
+ explicit Proxy(css::uno::Mapping to_from,
+ uno_Environment * pTo,
+ uno_Environment * pFrom,
+ uno_Interface * pUnoI,
+ typelib_InterfaceTypeDescription * pTypeDescr,
+ OUString const & rOId,
+ cppu::helper::purpenv::ProbeFun * probeFun,
+ void * pProbeContext);
+ ~Proxy();
+
+ void acquire();
+ void release();
+
+ void dispatch(
+ typelib_TypeDescriptionReference * pReturnTypeRef,
+ typelib_MethodParameter * pParams,
+ sal_Int32 nParams,
+ typelib_TypeDescription const * pMemberType,
+ void * pReturn,
+ void * pArgs[],
+ uno_Any ** ppException );
+
+};
+
+extern "C" void Proxy_free(uno_ExtEnvironment * pEnv, void * pProxy) SAL_THROW_EXTERN_C();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/helper/purpenv/helper_purpenv_Environment.cxx b/cppu/source/helper/purpenv/helper_purpenv_Environment.cxx
new file mode 100644
index 000000000..a0163939f
--- /dev/null
+++ b/cppu/source/helper/purpenv/helper_purpenv_Environment.cxx
@@ -0,0 +1,522 @@
+/* -*- 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 <cppu/helper/purpenv/Environment.hxx>
+
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <uno/lbnames.h>
+#include <cppu/Enterable.hxx>
+
+#include <typelib/typedescription.h>
+#include <osl/interlck.h>
+#include <memory>
+
+extern "C" {
+typedef void EnvFun_P (uno_Environment *);
+typedef void EnvFun_PP_P(uno_Environment ** ppHardEnv, uno_Environment *);
+typedef void ExtEnv_registerProxyInterface (uno_ExtEnvironment *,
+ void ** ppProxy,
+ uno_freeProxyFunc freeProxy,
+ rtl_uString * pOId,
+ typelib_InterfaceTypeDescription * pTypeDescr);
+typedef void ExtEnv_revokeInterface (uno_ExtEnvironment *,
+ void * pInterface);
+typedef void ExtEnv_getObjectIdentifier (uno_ExtEnvironment *,
+ rtl_uString **,
+ void *);
+typedef void ExtEnv_getRegisteredInterface (uno_ExtEnvironment *,
+ void **,
+ rtl_uString *,
+ typelib_InterfaceTypeDescription *);
+typedef void ExtEnv_getRegisteredInterfaces(uno_ExtEnvironment *,
+ void *** pppInterfaces,
+ sal_Int32 * pnLen,
+ uno_memAlloc memAlloc);
+typedef void ExtEnv_computeObjectIdentifier(uno_ExtEnvironment *,
+ rtl_uString ** ppOId,
+ void * pInterface);
+typedef void ExtEnv_acquireInterface (uno_ExtEnvironment *,
+ void * pInterface);
+typedef void ExtEnv_releaseInterface (uno_ExtEnvironment *,
+ void * pInterface);
+}
+
+namespace {
+
+class Base : public cppu::Enterable
+{
+public:
+ explicit Base(uno_Environment * pEnv, cppu::Enterable * pEnterable);
+
+ void acquireWeak();
+ void releaseWeak();
+ void harden (uno_Environment ** ppHardEnv);
+ void acquire();
+ void release();
+
+ void registerProxyInterface (void ** ppProxy,
+ uno_freeProxyFunc freeProxy,
+ OUString const & oid,
+ typelib_InterfaceTypeDescription * pTypeDescr);
+ void revokeInterface (void * pInterface);
+ void getObjectIdentifier (void * pInterface,
+ OUString * pOid);
+ void getRegisteredInterface (void **,
+ OUString const & oid,
+ typelib_InterfaceTypeDescription *);
+ void getRegisteredInterfaces(void ***,
+ sal_Int32 * pnLen,
+ uno_memAlloc memAlloc);
+ void computeObjectIdentifier(void * pInterface,
+ OUString * pOid);
+ void acquireInterface (void * pInterface);
+ void releaseInterface (void * pInterface);
+
+ virtual void v_enter() override;
+ virtual void v_leave() override;
+ virtual void v_callInto_v(uno_EnvCallee * pCallee, va_list * pParam) override;
+ virtual void v_callOut_v (uno_EnvCallee * pCallee, va_list * pParam) override;
+ virtual bool v_isValid (OUString * pReason) override;
+
+protected:
+ oslInterlockedCount m_nRef;
+ uno_Environment * m_pEnv;
+ std::unique_ptr<cppu::Enterable> m_pEnterable;
+
+ EnvFun_P * m_env_acquire;
+ EnvFun_P * m_env_release;
+ EnvFun_PP_P * m_env_harden;
+ EnvFun_P * m_env_acquireWeak;
+ EnvFun_P * m_env_releaseWeak;
+
+ ExtEnv_registerProxyInterface * m_env_registerProxyInterface;
+ ExtEnv_revokeInterface * m_env_revokeInterface;
+ ExtEnv_getObjectIdentifier * m_env_getObjectIdentifier;
+ ExtEnv_getRegisteredInterface * m_env_getRegisteredInterface;
+ ExtEnv_getRegisteredInterfaces * m_env_getRegisteredInterfaces;
+ ExtEnv_computeObjectIdentifier * m_env_computeObjectIdentifier;
+ ExtEnv_acquireInterface * m_env_acquireInterface;
+ ExtEnv_releaseInterface * m_env_releaseInterface;
+
+ virtual ~Base() override;
+};
+
+}
+
+extern "C" {
+static void s_acquire(uno_Environment * pEnv) //SAL_THROW_EXTERN_C()
+{
+ Base * pBase = static_cast<Base *>(pEnv->pReserved);
+ pBase->acquire();
+}
+
+static void s_release(uno_Environment * pEnv) SAL_THROW_EXTERN_C()
+{
+ Base * pBase = static_cast<Base *>(pEnv->pReserved);
+ pBase->release();
+}
+
+static void s_harden(uno_Environment ** ppHardEnv, uno_Environment * pEnv) SAL_THROW_EXTERN_C()
+{
+ Base * pBase = static_cast<Base *>(pEnv->pReserved);
+ pBase->harden(ppHardEnv);
+}
+
+static void s_acquireWeak(uno_Environment * pEnv) SAL_THROW_EXTERN_C()
+{
+ Base * pBase = static_cast<Base *>(pEnv->pReserved);
+ pBase->acquireWeak();
+}
+
+static void s_releaseWeak(uno_Environment * pEnv) SAL_THROW_EXTERN_C()
+{
+ Base * pBase = static_cast<Base *>(pEnv->pReserved);
+ pBase->releaseWeak();
+}
+
+
+static void s_registerProxyInterface(uno_ExtEnvironment * pExtEnv,
+ void ** ppProxy,
+ uno_freeProxyFunc freeProxy,
+ rtl_uString * pOId,
+ typelib_InterfaceTypeDescription * pTypeDescr)
+{
+ Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
+ pBase->registerProxyInterface(ppProxy, freeProxy, pOId, pTypeDescr);
+}
+
+static void s_revokeInterface(uno_ExtEnvironment * pExtEnv, void * pInterface)
+{
+ Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
+ pBase->revokeInterface(pInterface);
+}
+
+static void s_getObjectIdentifier(uno_ExtEnvironment * pExtEnv,
+ rtl_uString ** ppOId,
+ void * pInterface)
+{
+ Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
+ pBase->getObjectIdentifier(pInterface, reinterpret_cast<OUString *>(ppOId));
+}
+
+static void s_getRegisteredInterface(uno_ExtEnvironment * pExtEnv,
+ void ** ppInterface,
+ rtl_uString * pOId,
+ typelib_InterfaceTypeDescription * pTypeDescr)
+{
+ Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
+ pBase->getRegisteredInterface(ppInterface, pOId, pTypeDescr);
+}
+
+static void s_getRegisteredInterfaces(uno_ExtEnvironment * pExtEnv,
+ void *** pppInterface,
+ sal_Int32 * pnLen,
+ uno_memAlloc memAlloc)
+{
+ Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
+ pBase->getRegisteredInterfaces(pppInterface, pnLen, memAlloc);
+}
+
+static void s_computeObjectIdentifier(uno_ExtEnvironment * pExtEnv,
+ rtl_uString ** ppOId,
+ void * pInterface)
+{
+ Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
+ pBase->computeObjectIdentifier(pInterface, reinterpret_cast<OUString *>(ppOId));
+}
+
+static void s_acquireInterface(uno_ExtEnvironment * pExtEnv, void * pInterface) {
+ Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
+ pBase->acquireInterface(pInterface);
+}
+
+static void s_releaseInterface(uno_ExtEnvironment * pExtEnv, void * pInterface) {
+ Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
+ pBase->releaseInterface(pInterface);
+}
+
+}
+
+Base::Base(uno_Environment * pEnv, cppu::Enterable * pEnterable)
+ :m_nRef(1),
+ m_pEnv(pEnv),
+ m_pEnterable (pEnterable),
+ m_env_acquire (pEnv->acquire),
+ m_env_release (pEnv->release),
+ m_env_harden (pEnv->harden),
+ m_env_acquireWeak(pEnv->acquireWeak),
+ m_env_releaseWeak(pEnv->releaseWeak),
+ m_env_registerProxyInterface (pEnv->pExtEnv->registerProxyInterface),
+ m_env_revokeInterface (pEnv->pExtEnv->revokeInterface),
+ m_env_getObjectIdentifier (pEnv->pExtEnv->getObjectIdentifier),
+ m_env_getRegisteredInterface (pEnv->pExtEnv->getRegisteredInterface),
+ m_env_getRegisteredInterfaces(pEnv->pExtEnv->getRegisteredInterfaces),
+ m_env_computeObjectIdentifier(pEnv->pExtEnv->computeObjectIdentifier),
+ m_env_acquireInterface (pEnv->pExtEnv->acquireInterface),
+ m_env_releaseInterface (pEnv->pExtEnv->releaseInterface)
+{
+ SAL_INFO("cppu.purpenv", "LIFE: cppu::helper::purpenv::Base::Base(uno_Environment * pEnv) -> " << this);
+ OSL_ENSURE(
+ rtl_ustr_ascii_compare_WithLength(pEnv->pTypeName->buffer, rtl_str_getLength(UNO_LB_UNO), UNO_LB_UNO)
+ == 0,
+ "### wrong environment type!");
+
+ pEnv->acquire = s_acquire;
+ pEnv->release = s_release;
+ pEnv->harden = s_harden;
+ pEnv->acquireWeak = s_acquireWeak;
+ pEnv->releaseWeak = s_releaseWeak;
+
+ pEnv->pExtEnv->registerProxyInterface = s_registerProxyInterface;
+ pEnv->pExtEnv->revokeInterface = s_revokeInterface;
+ pEnv->pExtEnv->getObjectIdentifier = s_getObjectIdentifier;
+ pEnv->pExtEnv->getRegisteredInterface = s_getRegisteredInterface;
+ pEnv->pExtEnv->getRegisteredInterfaces = s_getRegisteredInterfaces;
+ pEnv->pExtEnv->computeObjectIdentifier = s_computeObjectIdentifier;
+ pEnv->pExtEnv->acquireInterface = s_acquireInterface;
+ pEnv->pExtEnv->releaseInterface = s_releaseInterface;
+
+ pEnv->pReserved = this;
+}
+
+Base::~Base()
+{
+ SAL_INFO("cppu.purpenv", "LIFE: cppu::helper::purpenv::Base::~Base() -> " << this);
+
+ m_pEnv->acquire = m_env_acquire;
+ m_pEnv->release = m_env_release;
+ m_pEnv->harden = m_env_harden;
+ m_pEnv->acquireWeak = m_env_acquireWeak;
+ m_pEnv->releaseWeak = m_env_releaseWeak;
+
+ m_pEnv->pReserved = nullptr;
+
+ m_pEnterable.reset();
+ m_pEnv->release(m_pEnv);
+}
+
+void Base::acquire()
+{
+ m_env_acquire(m_pEnv);
+
+ osl_atomic_increment(&m_nRef);
+}
+
+void Base::release()
+{
+ if (osl_atomic_decrement(&m_nRef) == 0)
+ delete this;
+
+ else
+ m_env_release(m_pEnv);
+}
+
+void Base::harden(uno_Environment ** ppHardEnv)
+{
+ m_env_harden(ppHardEnv, m_pEnv);
+ osl_atomic_increment(&m_nRef);
+}
+
+void Base::acquireWeak()
+{
+ m_env_acquireWeak(m_pEnv);
+}
+
+void Base::releaseWeak()
+{
+ m_env_releaseWeak(m_pEnv);
+}
+
+
+extern "C" { static void s_registerProxyInterface_v(va_list * pParam)
+{
+ uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *);
+ void ** ppProxy = va_arg(*pParam, void **);
+ uno_freeProxyFunc freeProxy = va_arg(*pParam, uno_freeProxyFunc);
+ rtl_uString * pOId = va_arg(*pParam, rtl_uString *);
+ typelib_InterfaceTypeDescription * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *);
+ ExtEnv_registerProxyInterface * pRegisterProxyInterface
+ = va_arg(*pParam, ExtEnv_registerProxyInterface *);
+
+ pRegisterProxyInterface(pExtEnv, ppProxy, freeProxy, pOId, pTypeDescr);
+}}
+
+void Base::registerProxyInterface(void ** ppProxy,
+ uno_freeProxyFunc freeProxy,
+ OUString const & oid,
+ typelib_InterfaceTypeDescription * pTypeDescr)
+{
+ uno_Environment_invoke(m_pEnv,
+ s_registerProxyInterface_v,
+ m_pEnv->pExtEnv,
+ ppProxy,
+ freeProxy,
+ oid.pData,
+ pTypeDescr,
+ m_env_registerProxyInterface);
+}
+
+
+extern "C" { static void s_revokeInterface_v(va_list * pParam)
+{
+ uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *);
+ void * pInterface = va_arg(*pParam, void *);
+ ExtEnv_revokeInterface * pRevokeInterface = va_arg(*pParam, ExtEnv_revokeInterface *);
+
+ pRevokeInterface(pExtEnv, pInterface);
+}}
+
+void Base::revokeInterface(void * pInterface)
+{
+ uno_Environment_invoke(m_pEnv,
+ s_revokeInterface_v,
+ m_pEnv->pExtEnv,
+ pInterface,
+ m_env_revokeInterface);
+}
+
+
+extern "C" { static void s_getObjectIdentifier_v(va_list * pParam)
+{
+ uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *);
+ void * pInterface = va_arg(*pParam, void *);
+ OUString * pOId = va_arg(*pParam, OUString *);
+ ExtEnv_getObjectIdentifier * pGetObjectIdentifier
+ = va_arg(*pParam, ExtEnv_getObjectIdentifier *);
+
+ pGetObjectIdentifier(pExtEnv, reinterpret_cast<rtl_uString **>(pOId), pInterface);
+}}
+
+void Base::getObjectIdentifier(void * pInterface, OUString * pOid)
+{
+ uno_Environment_invoke(m_pEnv,
+ s_getObjectIdentifier_v,
+ m_pEnv->pExtEnv,
+ pInterface,
+ pOid,
+ m_env_getObjectIdentifier);
+}
+
+
+extern "C" { static void s_getRegisteredInterface_v(va_list * pParam)
+{
+ uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *);
+ void ** ppInterface = va_arg(*pParam, void **);
+ rtl_uString * pOId = va_arg(*pParam, rtl_uString *);
+ typelib_InterfaceTypeDescription * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *);
+ ExtEnv_getRegisteredInterface * pGetRegisteredInterface
+ = va_arg(*pParam, ExtEnv_getRegisteredInterface *);
+
+ pGetRegisteredInterface(pExtEnv, ppInterface, pOId, pTypeDescr);
+}}
+
+void Base::getRegisteredInterface(void ** ppInterface,
+ OUString const & oid,
+ typelib_InterfaceTypeDescription * pTypeDescr)
+{
+ uno_Environment_invoke(m_pEnv,
+ s_getRegisteredInterface_v,
+ m_pEnv->pExtEnv,
+ ppInterface,
+ oid.pData,
+ pTypeDescr,
+ m_env_getRegisteredInterface);
+}
+
+
+extern "C" { static void s_getRegisteredInterfaces_v(va_list * pParam)
+{
+ uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *);
+ void *** pppInterface = va_arg(*pParam, void ***);
+ sal_Int32 * pnLen = va_arg(*pParam, sal_Int32 *);
+ uno_memAlloc memAlloc = va_arg(*pParam, uno_memAlloc);
+ ExtEnv_getRegisteredInterfaces * pGetRegisteredInterfaces
+ = va_arg(*pParam, ExtEnv_getRegisteredInterfaces *);
+
+ pGetRegisteredInterfaces(pExtEnv, pppInterface, pnLen, memAlloc);
+}}
+
+void Base::getRegisteredInterfaces(void *** pppInterface,
+ sal_Int32 * pnLen,
+ uno_memAlloc memAlloc)
+{
+ uno_Environment_invoke(m_pEnv,
+ s_getRegisteredInterfaces_v,
+ m_pEnv->pExtEnv,
+ pppInterface,
+ pnLen,
+ memAlloc,
+ m_env_getRegisteredInterfaces);
+}
+
+
+extern "C" { static void s_computeObjectIdentifier_v(va_list * pParam)
+{
+ uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *);
+ void * pInterface = va_arg(*pParam, void *);
+ OUString * pOId = va_arg(*pParam, OUString *);
+ ExtEnv_computeObjectIdentifier * pComputeObjectIdentifier
+ = va_arg(*pParam, ExtEnv_computeObjectIdentifier *);
+
+ pComputeObjectIdentifier(pExtEnv, reinterpret_cast<rtl_uString **>(pOId), pInterface);
+}}
+
+void Base::computeObjectIdentifier(void * pInterface, OUString * pOid)
+{
+ uno_Environment_invoke(m_pEnv,
+ s_computeObjectIdentifier_v,
+ m_pEnv->pExtEnv,
+ pInterface,
+ pOid,
+ m_env_computeObjectIdentifier);
+}
+
+
+extern "C" { static void s_acquireInterface_v(va_list * pParam)
+{
+ uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *);
+ void * pInterface = va_arg(*pParam, void *);
+ ExtEnv_acquireInterface * pAcquireInterface
+ = va_arg(*pParam, ExtEnv_acquireInterface *);
+
+ pAcquireInterface(pExtEnv, pInterface);
+}}
+
+void Base::acquireInterface(void * pInterface)
+{
+ uno_Environment_invoke(m_pEnv, s_acquireInterface_v, m_pEnv->pExtEnv, pInterface, m_env_acquireInterface);
+}
+
+
+extern "C" { static void s_releaseInterface_v(va_list * pParam)
+{
+ uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *);
+ void * pInterface = va_arg(*pParam, void *);
+ ExtEnv_releaseInterface * pReleaseInterface
+ = va_arg(*pParam, ExtEnv_releaseInterface *);
+
+ pReleaseInterface(pExtEnv, pInterface);
+}}
+
+void Base::releaseInterface(void * pInterface)
+{
+ uno_Environment_invoke(m_pEnv,
+ s_releaseInterface_v,
+ m_pEnv->pExtEnv,
+ pInterface,
+ m_env_releaseInterface);
+}
+
+void Base::v_enter()
+{
+ m_pEnterable->enter();
+}
+
+void Base::v_leave()
+{
+ m_pEnterable->leave();
+}
+
+void Base::v_callInto_v(uno_EnvCallee * pCallee, va_list * pParam)
+{
+ m_pEnterable->callInto_v(pCallee, pParam);
+}
+
+void Base::v_callOut_v(uno_EnvCallee * pCallee, va_list * pParam)
+{
+ m_pEnterable->callOut_v(pCallee, pParam);
+}
+
+bool Base::v_isValid(OUString * pReason)
+{
+ return m_pEnterable->isValid(pReason);
+}
+
+namespace cppu::helper::purpenv {
+
+void Environment_initWithEnterable(uno_Environment * pEnvironment, cppu::Enterable * pEnterable)
+{
+ new Base(pEnvironment, pEnterable);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/helper/purpenv/helper_purpenv_Mapping.cxx b/cppu/source/helper/purpenv/helper_purpenv_Mapping.cxx
new file mode 100644
index 000000000..f68a47390
--- /dev/null
+++ b/cppu/source/helper/purpenv/helper_purpenv_Mapping.cxx
@@ -0,0 +1,215 @@
+/* -*- 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 <cppu/helper/purpenv/Mapping.hxx>
+
+#include "Proxy.hxx"
+
+#include <osl/interlck.h>
+#include <sal/log.hxx>
+#include <uno/environment.hxx>
+#include <uno/dispatcher.h>
+
+using namespace com::sun::star;
+
+namespace {
+
+class Mapping : public uno_Mapping
+{
+ uno::Environment m_from;
+ uno::Environment m_to;
+
+ oslInterlockedCount m_nCount;
+
+ cppu::helper::purpenv::ProbeFun * m_probeFun;
+ void * m_pContext;
+
+public:
+ explicit Mapping(uno_Environment * pFrom,
+ uno_Environment * pTo,
+ cppu::helper::purpenv::ProbeFun * probeFun,
+ void * pProbeContext);
+ virtual ~Mapping();
+
+ void mapInterface(
+ uno_Interface ** ppOut,
+ uno_Interface * pUnoI,
+ typelib_InterfaceTypeDescription * pTypeDescr);
+
+ void acquire();
+ void release();
+};
+
+}
+
+static void s_mapInterface(
+ uno_Mapping * puno_Mapping,
+ void ** ppOut,
+ void * pUnoI,
+ typelib_InterfaceTypeDescription * pTypeDescr )
+ SAL_THROW_EXTERN_C()
+{
+ Mapping * pMapping = static_cast<Mapping *>(puno_Mapping);
+ pMapping->mapInterface(
+ reinterpret_cast<uno_Interface **>(ppOut),
+ static_cast<uno_Interface *>(pUnoI), pTypeDescr);
+}
+
+extern "C" {
+static void s_acquire(uno_Mapping * puno_Mapping)
+ SAL_THROW_EXTERN_C()
+{
+ Mapping * pMapping = static_cast<Mapping *>(puno_Mapping);
+ pMapping->acquire();
+}
+
+static void s_release(uno_Mapping * puno_Mapping)
+ SAL_THROW_EXTERN_C()
+{
+ Mapping * pMapping = static_cast<Mapping * >(puno_Mapping);
+ pMapping->release();
+}
+
+
+static void s_getIdentifier_v(va_list * pParam)
+{
+ uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
+ rtl_uString ** ppOid = va_arg(*pParam, rtl_uString **);
+ uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *);
+
+ pEnv->getObjectIdentifier(pEnv, ppOid, pUnoI);
+}
+
+static void s_free(uno_Mapping * puno_Mapping)
+ SAL_THROW_EXTERN_C()
+{
+ Mapping * pMapping = static_cast<Mapping *>(puno_Mapping);
+ delete pMapping;
+}
+}
+
+Mapping::Mapping(uno_Environment * pFrom,
+ uno_Environment * pTo,
+ cppu::helper::purpenv::ProbeFun * probeFun,
+ void * pProbeContext
+)
+ : m_from (pFrom),
+ m_to (pTo),
+ m_nCount (1),
+ m_probeFun(probeFun),
+ m_pContext(pProbeContext)
+{
+ SAL_INFO("cppu.purpenv", "LIFE: Mapping::Mapping(uno_Environment * pFrom, uno_Environment * pTo -> " << this);
+
+ uno_Mapping::acquire = s_acquire;
+ uno_Mapping::release = s_release;
+ uno_Mapping::mapInterface = s_mapInterface;
+}
+
+Mapping::~Mapping()
+{
+ SAL_INFO("cppu.purpenv", "LIFE: Mapping:~Mapping() -> " << this);
+}
+
+
+void Mapping::mapInterface(
+ uno_Interface ** ppOut,
+ uno_Interface * pUnoI,
+ typelib_InterfaceTypeDescription * pTypeDescr)
+{
+ OSL_ASSERT(ppOut && pTypeDescr);
+ if (*ppOut)
+ {
+ (*ppOut)->release(*ppOut);
+ *ppOut = nullptr;
+ }
+
+ if (!pUnoI)
+ return;
+
+ // get object id of uno interface to be wrapped
+ // need to enter environment because of potential "queryInterface" call
+ rtl_uString * pOId = nullptr;
+ uno_Environment_invoke(m_from.get(), s_getIdentifier_v, m_from.get(), &pOId, pUnoI);
+ OSL_ASSERT(pOId);
+
+ // try to get any known interface from target environment
+ m_to.get()->pExtEnv->getRegisteredInterface(m_to.get()->pExtEnv, reinterpret_cast<void **>(ppOut), pOId, pTypeDescr);
+
+ if (!*ppOut) // not yet there, register new proxy interface
+ {
+ // try to publish a new proxy (ref count initially 1)
+ uno_Interface * pProxy = new Proxy(this,
+ m_from.get(),
+ m_to.get(),
+ pUnoI,
+ pTypeDescr,
+ pOId,
+ m_probeFun,
+ m_pContext);
+
+ // proxy may be exchanged during registration
+ m_to.get()->pExtEnv->registerProxyInterface(m_to.get()->pExtEnv,
+ reinterpret_cast<void **>(&pProxy),
+ Proxy_free,
+ pOId,
+ pTypeDescr);
+
+ *ppOut = pProxy;
+ }
+
+ rtl_uString_release(pOId);
+}
+
+
+void Mapping::acquire()
+{
+ if (osl_atomic_increment(&m_nCount) == 1)
+ {
+ uno_Mapping * pMapping = this;
+
+ ::uno_registerMapping(&pMapping, s_free, m_from.get(), m_to.get(), nullptr);
+ }
+}
+
+void Mapping::release()
+{
+ if (osl_atomic_decrement(&m_nCount) == 0)
+ ::uno_revokeMapping(this);
+}
+
+
+namespace cppu::helper::purpenv {
+
+void createMapping(uno_Mapping ** ppMapping,
+ uno_Environment * pFrom,
+ uno_Environment * pTo,
+ ProbeFun * probeFun,
+ void * pContext
+ )
+{
+ *ppMapping = new Mapping(pFrom, pTo, probeFun, pContext);
+
+ ::uno_registerMapping(ppMapping, s_free, pFrom, pTo, nullptr);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/helper/purpenv/helper_purpenv_Proxy.cxx b/cppu/source/helper/purpenv/helper_purpenv_Proxy.cxx
new file mode 100644
index 000000000..db4820fc9
--- /dev/null
+++ b/cppu/source/helper/purpenv/helper_purpenv_Proxy.cxx
@@ -0,0 +1,504 @@
+/* -*- 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 "Proxy.hxx"
+
+#include <sal/log.hxx>
+#include <uno/dispatcher.h>
+#include <typelib/typedescription.hxx>
+#include <utility>
+
+using namespace com::sun::star;
+
+static bool relatesToInterface(typelib_TypeDescription * pTypeDescr)
+{
+ switch (pTypeDescr->eTypeClass)
+ {
+// case typelib_TypeClass_TYPEDEF:
+ case typelib_TypeClass_SEQUENCE:
+ {
+ switch (reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType->eTypeClass)
+ {
+ case typelib_TypeClass_INTERFACE:
+ case typelib_TypeClass_ANY: // might relate to interface
+ return true;
+ case typelib_TypeClass_SEQUENCE:
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ typelib_TypeDescription * pTD = nullptr;
+ TYPELIB_DANGER_GET( &pTD, reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType );
+ bool bRel = relatesToInterface( pTD );
+ TYPELIB_DANGER_RELEASE( pTD );
+ return bRel;
+ }
+ default:
+ ;
+ }
+ return false;
+ }
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ // ...optimized... to avoid getDescription() calls!
+ typelib_CompoundTypeDescription * pComp = reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr);
+ typelib_TypeDescriptionReference ** pTypes = pComp->ppTypeRefs;
+ for ( sal_Int32 nPos = pComp->nMembers; nPos--; )
+ {
+ switch (pTypes[nPos]->eTypeClass)
+ {
+ case typelib_TypeClass_INTERFACE:
+ case typelib_TypeClass_ANY: // might relate to interface
+ return true;
+// case typelib_TypeClass_TYPEDEF:
+ case typelib_TypeClass_SEQUENCE:
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ typelib_TypeDescription * pTD = nullptr;
+ TYPELIB_DANGER_GET( &pTD, pTypes[nPos] );
+ bool bRel = relatesToInterface( pTD );
+ TYPELIB_DANGER_RELEASE( pTD );
+ if (bRel)
+ return true;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ if (pComp->pBaseTypeDescription)
+ return relatesToInterface( &pComp->pBaseTypeDescription->aBase );
+ break;
+ }
+ case typelib_TypeClass_ANY: // might relate to interface
+ case typelib_TypeClass_INTERFACE:
+ return true;
+
+ default:
+ ;
+ }
+ return false;
+}
+
+extern "C" { static void s_Proxy_dispatch(
+ uno_Interface * pUnoI,
+ typelib_TypeDescription const * pMemberType,
+ void * pReturn,
+ void * pArgs[],
+ uno_Any ** ppException)
+ SAL_THROW_EXTERN_C()
+{
+ Proxy * pThis = static_cast<Proxy *>(pUnoI);
+
+ typelib_MethodParameter param;
+ sal_Int32 nParams = 0;
+ typelib_MethodParameter * pParams = nullptr;
+ typelib_TypeDescriptionReference * pReturnTypeRef = nullptr;
+ // sal_Int32 nOutParams = 0;
+
+ switch (pMemberType->eTypeClass)
+ {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ if (pReturn)
+ {
+ pReturnTypeRef =
+ reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>(
+ pMemberType)->pAttributeTypeRef;
+ nParams = 0;
+ pParams = nullptr;
+ }
+ else
+ {
+ param.pTypeRef = reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>(
+ pMemberType)->pAttributeTypeRef;
+ param.bIn = true;
+ param.bOut = false;
+ nParams = 1;
+ pParams = &param;
+ }
+ break;
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ typelib_InterfaceMethodTypeDescription const * method_td =
+ reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(pMemberType);
+ pReturnTypeRef = method_td->pReturnTypeRef;
+ nParams = method_td->nParams;
+ pParams = method_td->pParams;
+ break;
+ }
+ default:
+ OSL_FAIL( "### illegal member typeclass!" );
+ abort();
+ }
+
+ pThis->dispatch( pReturnTypeRef,
+ pParams,
+ nParams,
+ pMemberType,
+ pReturn,
+ pArgs,
+ ppException );
+}}
+
+extern "C" void Proxy_free(SAL_UNUSED_PARAMETER uno_ExtEnvironment * /*pEnv*/, void * pProxy) SAL_THROW_EXTERN_C()
+{
+ Proxy * pThis = static_cast<Proxy * >(static_cast<uno_Interface *>(pProxy));
+ delete pThis;
+}
+
+extern "C" {
+static void s_Proxy_acquire(uno_Interface * pUnoI) SAL_THROW_EXTERN_C()
+{
+ Proxy * pProxy = static_cast<Proxy *>(pUnoI);
+ pProxy->acquire();
+}
+
+static void s_Proxy_release(uno_Interface * pUnoI) SAL_THROW_EXTERN_C()
+{
+ Proxy * pProxy = static_cast<Proxy *>(pUnoI);
+ pProxy->release();
+}
+
+static void s_acquireAndRegister_v(va_list * pParam)
+{
+ uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *);
+ rtl_uString * pOid = va_arg(*pParam, rtl_uString *);
+ typelib_InterfaceTypeDescription * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *);
+ uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
+
+ pUnoI->acquire(pUnoI);
+ pEnv->registerInterface(pEnv, reinterpret_cast<void **>(&pUnoI), pOid, pTypeDescr);
+}
+}
+
+Proxy::Proxy(uno::Mapping to_from,
+ uno_Environment * pTo,
+ uno_Environment * pFrom,
+ uno_Interface * pUnoI,
+ typelib_InterfaceTypeDescription * pTypeDescr,
+ OUString const & rOId,
+ cppu::helper::purpenv::ProbeFun * probeFun,
+ void * pProbeContext
+)
+ : m_nRef (1),
+ m_from (pFrom),
+ m_to (pTo),
+ m_from_to (pFrom, pTo),
+ m_to_from (std::move(to_from)),
+ m_pUnoI (pUnoI),
+ m_pTypeDescr (pTypeDescr),
+ m_aOId (rOId),
+ m_probeFun (probeFun),
+ m_pProbeContext(pProbeContext)
+{
+ SAL_INFO("cppu.purpenv", "LIFE: Proxy::Proxy(<>) -> " << this);
+
+ typelib_typedescription_acquire(&m_pTypeDescr->aBase);
+ if (!m_pTypeDescr->aBase.bComplete)
+ typelib_typedescription_complete(reinterpret_cast<typelib_TypeDescription **>(&m_pTypeDescr));
+
+ OSL_ENSURE(m_pTypeDescr->aBase.bComplete, "### type is incomplete!");
+
+ uno_Environment_invoke(m_to.get(), s_acquireAndRegister_v, m_pUnoI, rOId.pData, pTypeDescr, m_to.get());
+
+ // uno_Interface
+ uno_Interface::acquire = s_Proxy_acquire;
+ uno_Interface::release = s_Proxy_release;
+ uno_Interface::pDispatcher = s_Proxy_dispatch;
+}
+
+extern "C" { static void s_releaseAndRevoke_v(va_list * pParam)
+{
+ uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
+ uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *);
+
+ pEnv->revokeInterface(pEnv, pUnoI);
+ pUnoI->release(pUnoI);
+}}
+
+Proxy::~Proxy()
+{
+ SAL_INFO("cppu.purpenv", "LIFE: Proxy::~Proxy() -> " << this);
+
+ uno_Environment_invoke(m_to.get(), s_releaseAndRevoke_v, m_to.get(), m_pUnoI);
+
+ typelib_typedescription_release(&m_pTypeDescr->aBase);
+}
+
+static uno::TypeDescription getAcquireMethod()
+{
+ typelib_TypeDescriptionReference * type_XInterface =
+ * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE);
+
+ typelib_TypeDescription * pTXInterfaceDescr = nullptr;
+ TYPELIB_DANGER_GET (&pTXInterfaceDescr, type_XInterface);
+ uno::TypeDescription acquire(
+ reinterpret_cast< typelib_InterfaceTypeDescription * >(
+ pTXInterfaceDescr)->ppAllMembers[1]);
+ TYPELIB_DANGER_RELEASE(pTXInterfaceDescr);
+
+ return acquire;
+}
+
+static uno::TypeDescription getReleaseMethod()
+{
+ typelib_TypeDescriptionReference * type_XInterface =
+ * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE);
+
+ typelib_TypeDescription * pTXInterfaceDescr = nullptr;
+ TYPELIB_DANGER_GET (&pTXInterfaceDescr, type_XInterface);
+ uno::TypeDescription release(
+ reinterpret_cast< typelib_InterfaceTypeDescription * >(
+ pTXInterfaceDescr)->ppAllMembers[2]);
+ TYPELIB_DANGER_RELEASE(pTXInterfaceDescr);
+
+ return release;
+}
+
+static uno::TypeDescription s_acquireMethod(getAcquireMethod());
+static uno::TypeDescription s_releaseMethod(getReleaseMethod());
+
+void Proxy::acquire()
+{
+ if (m_probeFun)
+ m_probeFun(true,
+ this,
+ m_pProbeContext,
+ *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
+ nullptr,
+ 0,
+ s_acquireMethod.get(),
+ nullptr,
+ nullptr,
+ nullptr);
+
+ if (osl_atomic_increment(&m_nRef) == 1)
+ {
+ // rebirth of proxy zombie
+ void * pThis = this;
+ m_from.get()->pExtEnv->registerProxyInterface(m_from.get()->pExtEnv,
+ &pThis,
+ Proxy_free,
+ m_aOId.pData,
+ m_pTypeDescr);
+ OSL_ASSERT(pThis == this);
+ }
+
+ if (m_probeFun)
+ m_probeFun(false,
+ this,
+ m_pProbeContext,
+ *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
+ nullptr,
+ 0,
+ s_acquireMethod.get(),
+ nullptr,
+ nullptr,
+ nullptr);
+
+}
+
+void Proxy::release()
+{
+ cppu::helper::purpenv::ProbeFun * probeFun = m_probeFun;
+ void * pProbeContext = m_pProbeContext;
+
+ if (m_probeFun)
+ m_probeFun(true,
+ this,
+ m_pProbeContext,
+ *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
+ nullptr,
+ 0,
+ s_releaseMethod.get(),
+ nullptr,
+ nullptr,
+ nullptr);
+
+ if (osl_atomic_decrement(&m_nRef) == 0)
+ m_from.get()->pExtEnv->revokeInterface(m_from.get()->pExtEnv, this);
+
+ if (probeFun)
+ probeFun(false,
+ this,
+ pProbeContext,
+ *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
+ nullptr,
+ 0,
+ s_releaseMethod.get(),
+ nullptr,
+ nullptr,
+ nullptr);
+
+}
+
+
+extern "C" {
+static void s_type_destructData_v(va_list * pParam)
+{
+ void * ret = va_arg(*pParam, void *);
+ typelib_TypeDescriptionReference * pReturnTypeRef = va_arg(*pParam, typelib_TypeDescriptionReference *);
+
+ uno_type_destructData(ret, pReturnTypeRef, nullptr);
+}
+
+static void s_dispatcher_v(va_list * pParam)
+{
+ uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *);
+ typelib_TypeDescription const * pMemberType = va_arg(*pParam, typelib_TypeDescription const *);
+ void * pReturn = va_arg(*pParam, void *);
+ void ** pArgs = va_arg(*pParam, void **);
+ uno_Any ** ppException = va_arg(*pParam, uno_Any **);
+
+ pUnoI->pDispatcher(pUnoI, pMemberType, pReturn, pArgs, ppException);
+}
+}
+
+void Proxy::dispatch(typelib_TypeDescriptionReference * pReturnTypeRef,
+ typelib_MethodParameter * pParams,
+ sal_Int32 nParams,
+ typelib_TypeDescription const * pMemberType,
+ void * pReturn,
+ void * pArgs[],
+ uno_Any ** ppException)
+{
+ if (m_probeFun)
+ m_probeFun(true,
+ this,
+ m_pProbeContext,
+ pReturnTypeRef,
+ pParams,
+ nParams,
+ pMemberType,
+ pReturn,
+ pArgs,
+ ppException);
+
+ void ** args = static_cast<void **>(alloca( sizeof (void *) * nParams ));
+
+ typelib_TypeDescription * return_td = nullptr;
+ void * ret = pReturn;
+ if (pReturnTypeRef)
+ {
+ TYPELIB_DANGER_GET(&return_td, pReturnTypeRef);
+
+ if (relatesToInterface(return_td))
+ ret = alloca(return_td->nSize);
+
+ TYPELIB_DANGER_RELEASE(return_td);
+ }
+
+ for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
+ {
+ typelib_MethodParameter const & param = pParams[nPos];
+ typelib_TypeDescription * td = nullptr;
+ TYPELIB_DANGER_GET( &td, param.pTypeRef );
+ if (relatesToInterface(td))
+ {
+ args[nPos] = alloca(td->nSize);
+ if (param.bIn)
+ {
+ uno_copyAndConvertData(args[nPos], pArgs[nPos], td, m_from_to.get());
+ }
+ }
+ else
+ {
+ args[nPos] = pArgs[nPos];
+ }
+ TYPELIB_DANGER_RELEASE( td );
+ }
+
+ uno_Any exc_data;
+ uno_Any * exc = &exc_data;
+
+ // do the UNO call...
+ uno_Environment_invoke(m_to.get(), s_dispatcher_v, m_pUnoI, pMemberType, ret, args, &exc);
+
+ if (exc == nullptr)
+ {
+ for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
+ {
+ if (args[nPos] != pArgs[nPos])
+ {
+ typelib_MethodParameter const & param = pParams[nPos];
+ if (param.bOut)
+ {
+ if (param.bIn) // is inout
+ {
+ uno_type_destructData(pArgs[nPos], param.pTypeRef, nullptr);
+ }
+ uno_type_copyAndConvertData(pArgs[ nPos ],
+ args[ nPos ],
+ param.pTypeRef,
+ m_to_from.get());
+ }
+ uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0);
+ }
+ }
+ if (ret != pReturn)
+ {
+ uno_type_copyAndConvertData(pReturn,
+ ret,
+ pReturnTypeRef,
+ m_to_from.get());
+
+ uno_Environment_invoke(m_to.get(), s_type_destructData_v, ret, pReturnTypeRef, 0);
+ }
+
+ *ppException = nullptr;
+ }
+ else // exception occurred
+ {
+ for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
+ {
+ if (args[nPos] != pArgs[nPos])
+ {
+ typelib_MethodParameter const & param = pParams[nPos];
+ if (param.bIn)
+ {
+ uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0);
+ }
+ }
+ }
+
+ uno_type_any_constructAndConvert(*ppException,
+ exc->pData,
+ exc->pType,
+ m_to_from.get());
+
+ // FIXME: need to destruct in m_to
+ uno_any_destruct(exc, nullptr);
+ }
+
+ if (m_probeFun)
+ m_probeFun(false,
+ this,
+ m_pProbeContext,
+ pReturnTypeRef,
+ pParams,
+ nParams,
+ pMemberType,
+ pReturn,
+ pArgs,
+ ppException);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/threadpool/current.cxx b/cppu/source/threadpool/current.cxx
new file mode 100644
index 000000000..64e6bfb8f
--- /dev/null
+++ b/cppu/source/threadpool/current.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 <sal/config.h>
+
+#include <rtl/byteseq.h>
+#include <osl/mutex.hxx>
+
+#include <uno/current_context.h>
+#include <uno/environment.hxx>
+#include <uno/mapping.hxx>
+#include <typelib/typedescription.h>
+
+#include "current.hxx"
+
+
+using namespace ::osl;
+using namespace ::rtl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+
+namespace cppu
+{
+
+static typelib_InterfaceTypeDescription * get_type_XCurrentContext()
+{
+ static typelib_InterfaceTypeDescription* s_type_XCurrentContext = []() {
+ OUString sTypeName("com.sun.star.uno.XCurrentContext");
+ typelib_InterfaceTypeDescription* pTD = nullptr;
+ typelib_TypeDescriptionReference* pMembers[1] = { nullptr };
+ OUString sMethodName0("com.sun.star.uno.XCurrentContext::getValueByName");
+ typelib_typedescriptionreference_new(&pMembers[0], typelib_TypeClass_INTERFACE_METHOD,
+ sMethodName0.pData);
+ typelib_typedescription_newInterface(
+ &pTD, sTypeName.pData, 0, 0, 0, 0, 0,
+ *typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE), 1, pMembers);
+
+ typelib_typedescription_register(reinterpret_cast<typelib_TypeDescription**>(&pTD));
+ typelib_typedescriptionreference_release(pMembers[0]);
+
+ typelib_InterfaceMethodTypeDescription* pMethod = nullptr;
+ typelib_Parameter_Init aParameters[1];
+ OUString sParamName0("Name");
+ OUString sParamType0("string");
+ aParameters[0].pParamName = sParamName0.pData;
+ aParameters[0].eTypeClass = typelib_TypeClass_STRING;
+ aParameters[0].pTypeName = sParamType0.pData;
+ aParameters[0].bIn = true;
+ aParameters[0].bOut = false;
+ rtl_uString* pExceptions[1];
+ OUString sExceptionName0("com.sun.star.uno.RuntimeException");
+ pExceptions[0] = sExceptionName0.pData;
+ OUString sReturnType0("any");
+ typelib_typedescription_newInterfaceMethod(&pMethod, 3, false, sMethodName0.pData,
+ typelib_TypeClass_ANY, sReturnType0.pData, 1,
+ aParameters, 1, pExceptions);
+ typelib_typedescription_register(reinterpret_cast<typelib_TypeDescription**>(&pMethod));
+ typelib_typedescription_release(&pMethod->aBase.aBase);
+ // another static ref:
+ ++reinterpret_cast<typelib_TypeDescription*>(pTD)->nStaticRefCount;
+ return pTD;
+ }();
+
+ return s_type_XCurrentContext;
+}
+
+IdContainer::IdContainer()
+ : pCurrentContext(nullptr)
+ , pCurrentContextEnv(nullptr)
+ , pLocalThreadId(nullptr)
+ , pCurrentId(nullptr)
+ , nRefCountOfCurrentId(0)
+ , bInit(false)
+{
+}
+
+IdContainer::~IdContainer()
+{
+ if (pCurrentContext)
+ {
+ (*pCurrentContextEnv->releaseInterface)(
+ pCurrentContextEnv, pCurrentContext );
+ (*pCurrentContextEnv->aBase.release)(
+ &pCurrentContextEnv->aBase );
+ }
+ if (bInit)
+ {
+ ::rtl_byte_sequence_release( pLocalThreadId );
+ ::rtl_byte_sequence_release( pCurrentId );
+ }
+}
+
+IdContainer& getIdContainer()
+{
+ static thread_local IdContainer aId;
+ return aId;
+}
+
+}
+
+extern "C" sal_Bool SAL_CALL uno_setCurrentContext(
+ void * pCurrentContext,
+ rtl_uString * pEnvTypeName, void * pEnvContext )
+ SAL_THROW_EXTERN_C()
+{
+ IdContainer& id = getIdContainer();
+
+ // free old one
+ if (id.pCurrentContext)
+ {
+ (*id.pCurrentContextEnv->releaseInterface)(
+ id.pCurrentContextEnv, id.pCurrentContext );
+ (*id.pCurrentContextEnv->aBase.release)(
+ &id.pCurrentContextEnv->aBase );
+ id.pCurrentContextEnv = nullptr;
+
+ id.pCurrentContext = nullptr;
+ }
+
+ if (!pCurrentContext)
+ return true;
+
+ uno_Environment * pEnv = nullptr;
+ ::uno_getEnvironment( &pEnv, pEnvTypeName, pEnvContext );
+ OSL_ASSERT( pEnv && pEnv->pExtEnv );
+ if (pEnv)
+ {
+ if (pEnv->pExtEnv)
+ {
+ id.pCurrentContextEnv = pEnv->pExtEnv;
+ (*id.pCurrentContextEnv->acquireInterface)(
+ id.pCurrentContextEnv, pCurrentContext );
+ id.pCurrentContext = pCurrentContext;
+ }
+ else
+ {
+ (*pEnv->release)( pEnv );
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ return true;
+}
+
+extern "C" sal_Bool SAL_CALL uno_getCurrentContext(
+ void ** ppCurrentContext, rtl_uString * pEnvTypeName, void * pEnvContext )
+ SAL_THROW_EXTERN_C()
+{
+ IdContainer& id = getIdContainer();
+
+ Environment target_env;
+
+ // release inout parameter
+ if (*ppCurrentContext)
+ {
+ target_env = Environment(OUString(pEnvTypeName), pEnvContext);
+ OSL_ASSERT( target_env.is() );
+ if (! target_env.is())
+ return false;
+ uno_ExtEnvironment * pEnv = target_env.get()->pExtEnv;
+ OSL_ASSERT( nullptr != pEnv );
+ if (nullptr == pEnv)
+ return false;
+ (*pEnv->releaseInterface)( pEnv, *ppCurrentContext );
+
+ *ppCurrentContext = nullptr;
+ }
+
+ // case: null-ref
+ if (nullptr == id.pCurrentContext)
+ return true;
+
+ if (! target_env.is())
+ {
+ target_env = Environment(OUString(pEnvTypeName), pEnvContext);
+ OSL_ASSERT( target_env.is() );
+ if (! target_env.is())
+ return false;
+ }
+
+ Mapping mapping(&id.pCurrentContextEnv->aBase, target_env.get());
+ OSL_ASSERT( mapping.is() );
+ if (! mapping.is())
+ return false;
+
+ mapping.mapInterface(ppCurrentContext, id.pCurrentContext, ::cppu::get_type_XCurrentContext());
+
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/threadpool/current.hxx b/cppu/source/threadpool/current.hxx
new file mode 100644
index 000000000..1f6ce6642
--- /dev/null
+++ b/cppu/source/threadpool/current.hxx
@@ -0,0 +1,47 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <sal/types.h>
+
+struct _uno_ExtEnvironment;
+
+namespace cppu
+{
+struct IdContainer
+{
+ void * pCurrentContext;
+ _uno_ExtEnvironment * pCurrentContextEnv;
+
+ sal_Sequence * pLocalThreadId;
+ sal_Sequence * pCurrentId;
+ sal_Int32 nRefCountOfCurrentId;
+ bool bInit;
+
+ IdContainer();
+ ~IdContainer();
+};
+
+IdContainer& getIdContainer();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/threadpool/jobqueue.cxx b/cppu/source/threadpool/jobqueue.cxx
new file mode 100644
index 000000000..1be424024
--- /dev/null
+++ b/cppu/source/threadpool/jobqueue.cxx
@@ -0,0 +1,177 @@
+/* -*- 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 <cassert>
+
+#include "jobqueue.hxx"
+#include "threadpool.hxx"
+
+namespace cppu_threadpool {
+
+ JobQueue::JobQueue() :
+ m_nToDo( 0 ),
+ m_bSuspended( false ),
+ m_DisposedCallerAdmin( DisposedCallerAdmin::getInstance() )
+ {
+ }
+
+ void JobQueue::add( void *pThreadSpecificData, RequestFun * doRequest )
+ {
+ std::scoped_lock guard( m_mutex );
+ Job job = { pThreadSpecificData , doRequest };
+ m_lstJob.push_back( job );
+ if( ! m_bSuspended )
+ {
+ m_cndWait.notify_all();
+ }
+ m_nToDo ++;
+ }
+
+ void *JobQueue::enter( void const * nDisposeId , bool bReturnWhenNoJob )
+ {
+ void *pReturn = nullptr;
+ {
+ // synchronize with the dispose calls
+ std::scoped_lock guard( m_mutex );
+ if( m_DisposedCallerAdmin->isDisposed( nDisposeId ) )
+ {
+ return nullptr;
+ }
+ m_lstCallstack.push_front( nDisposeId );
+ }
+
+
+ while( true )
+ {
+ struct Job job={nullptr,nullptr};
+ {
+ std::unique_lock guard( m_mutex );
+
+ while (m_bSuspended
+ || (m_lstCallstack.front() != nullptr && !bReturnWhenNoJob
+ && m_lstJob.empty()))
+ {
+ m_cndWait.wait(guard);
+ }
+
+ if( nullptr == m_lstCallstack.front() )
+ {
+ // disposed !
+ if (!m_lstJob.empty() && m_lstJob.front().doRequest == nullptr) {
+ // If this thread was waiting for a remote response, that response may or
+ // may not have been enqueued; if it has not been enqueued, there cannot be
+ // another enqueued response, so it is always correct to remove any enqueued
+ // response here:
+ m_lstJob.pop_front();
+ }
+ break;
+ }
+
+ if( m_lstJob.empty() )
+ {
+ assert(bReturnWhenNoJob);
+ break;
+ }
+
+ job = m_lstJob.front();
+ m_lstJob.pop_front();
+ }
+
+ if( job.doRequest )
+ {
+ job.doRequest( job.pThreadSpecificData );
+ std::scoped_lock guard( m_mutex );
+ m_nToDo --;
+ }
+ else
+ {
+ pReturn = job.pThreadSpecificData;
+ std::scoped_lock guard( m_mutex );
+ m_nToDo --;
+ break;
+ }
+ }
+
+ {
+ // synchronize with the dispose calls
+ std::scoped_lock guard( m_mutex );
+ m_lstCallstack.pop_front();
+ }
+
+ return pReturn;
+ }
+
+ void JobQueue::dispose( void const * nDisposeId )
+ {
+ std::scoped_lock guard( m_mutex );
+ for( auto& rId : m_lstCallstack )
+ {
+ if( rId == nDisposeId )
+ {
+ rId = nullptr;
+ }
+ }
+
+ if( !m_lstCallstack.empty() && ! m_lstCallstack.front() )
+ {
+ // The thread is waiting for a disposed pCallerId, let it go
+ m_cndWait.notify_all();
+ }
+ }
+
+ void JobQueue::suspend()
+ {
+ std::scoped_lock guard( m_mutex );
+ m_bSuspended = true;
+ }
+
+ void JobQueue::resume()
+ {
+ std::scoped_lock guard( m_mutex );
+ m_bSuspended = false;
+ if( ! m_lstJob.empty() )
+ {
+ m_cndWait.notify_all();
+ }
+ }
+
+ bool JobQueue::isEmpty() const
+ {
+ std::scoped_lock guard( m_mutex );
+ return m_lstJob.empty();
+ }
+
+ bool JobQueue::isCallstackEmpty() const
+ {
+ std::scoped_lock guard( m_mutex );
+ return m_lstCallstack.empty();
+ }
+
+ bool JobQueue::isBusy() const
+ {
+ std::scoped_lock guard( m_mutex );
+ return m_nToDo > 0;
+ }
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/threadpool/jobqueue.hxx b/cppu/source/threadpool/jobqueue.hxx
new file mode 100644
index 000000000..5b92f2476
--- /dev/null
+++ b/cppu/source/threadpool/jobqueue.hxx
@@ -0,0 +1,72 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <condition_variable>
+#include <deque>
+#include <memory>
+#include <mutex>
+
+#include <sal/types.h>
+
+namespace cppu_threadpool
+{
+ extern "C" typedef void (RequestFun)(void *);
+
+ struct Job
+ {
+ void *pThreadSpecificData;
+ RequestFun * doRequest;
+ };
+
+ class DisposedCallerAdmin;
+ typedef std::shared_ptr<DisposedCallerAdmin> DisposedCallerAdminHolder;
+
+ class JobQueue
+ {
+ public:
+ JobQueue();
+
+ void add( void *pThreadSpecificData, RequestFun * doRequest );
+
+ void *enter( void const * nDisposeId , bool bReturnWhenNoJob = false );
+ void dispose( void const * nDisposeId );
+
+ void suspend();
+ void resume();
+
+ bool isEmpty() const;
+ bool isCallstackEmpty() const;
+ bool isBusy() const;
+
+ private:
+ mutable std::mutex m_mutex;
+ std::deque < struct Job > m_lstJob;
+ std::deque<void const *> m_lstCallstack;
+ sal_Int32 m_nToDo;
+ bool m_bSuspended;
+ std::condition_variable m_cndWait;
+ DisposedCallerAdminHolder m_DisposedCallerAdmin;
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/threadpool/thread.cxx b/cppu/source/threadpool/thread.cxx
new file mode 100644
index 000000000..56e52838b
--- /dev/null
+++ b/cppu/source/threadpool/thread.cxx
@@ -0,0 +1,198 @@
+/* -*- 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 <algorithm>
+#include <cstdlib>
+#include <osl/diagnose.h>
+#include <uno/threadpool.h>
+#include <sal/log.hxx>
+#include <utility>
+
+#include "thread.hxx"
+#include "jobqueue.hxx"
+#include "threadpool.hxx"
+
+using namespace osl;
+using namespace rtl;
+
+namespace cppu_threadpool {
+
+
+ ThreadAdmin::ThreadAdmin(): m_disposed(false) {}
+
+ ThreadAdmin::~ThreadAdmin()
+ {
+ SAL_WARN_IF(m_deque.size(), "cppu.threadpool", m_deque.size() << "Threads left");
+ }
+
+ bool ThreadAdmin::add_locked( rtl::Reference< ORequestThread > const & p )
+ {
+ if( m_disposed )
+ {
+ return false;
+ }
+ m_deque.push_back( p );
+ return true;
+ }
+
+ void ThreadAdmin::remove_locked( rtl::Reference< ORequestThread > const & p )
+ {
+ m_deque.erase(std::find( m_deque.begin(), m_deque.end(), p ), m_deque.end());
+ }
+
+ void ThreadAdmin::remove( rtl::Reference< ORequestThread > const & p )
+ {
+ std::scoped_lock aGuard( m_mutex );
+ remove_locked( p );
+ }
+
+ void ThreadAdmin::join()
+ {
+ {
+ std::scoped_lock aGuard( m_mutex );
+ m_disposed = true;
+ }
+ for (;;)
+ {
+ rtl::Reference< ORequestThread > pCurrent;
+ {
+ std::scoped_lock aGuard( m_mutex );
+ if( m_deque.empty() )
+ {
+ break;
+ }
+ pCurrent = m_deque.front();
+ m_deque.pop_front();
+ }
+ if (pCurrent->getIdentifier()
+ != osl::Thread::getCurrentIdentifier())
+ {
+ pCurrent->join();
+ }
+ }
+ }
+
+
+ ORequestThread::ORequestThread( ThreadPoolHolder aThreadPool,
+ JobQueue *pQueue,
+ ByteSequence aThreadId,
+ bool bAsynchron )
+ : m_aThreadPool(std::move( aThreadPool ))
+ , m_pQueue( pQueue )
+ , m_aThreadId(std::move( aThreadId ))
+ , m_bAsynchron( bAsynchron )
+ {}
+
+ ORequestThread::~ORequestThread() {}
+
+ void ORequestThread::setTask( JobQueue *pQueue,
+ const ByteSequence &aThreadId,
+ bool bAsynchron )
+ {
+ m_pQueue = pQueue;
+ m_aThreadId = aThreadId;
+ m_bAsynchron = bAsynchron;
+ }
+
+ bool ORequestThread::launch()
+ {
+ // Assumption is that osl::Thread::create returns normally with a true
+ // return value iff it causes osl::Thread::run to start executing:
+ acquire();
+ ThreadAdmin & rThreadAdmin = m_aThreadPool->getThreadAdmin();
+ std::unique_lock g(rThreadAdmin.m_mutex);
+ if (!rThreadAdmin.add_locked( this )) {
+ return false;
+ }
+ try {
+ if (!create()) {
+ std::abort();
+ }
+ } catch (...) {
+ rThreadAdmin.remove_locked( this );
+ g.release();
+ release();
+ throw;
+ }
+ return true;
+ }
+
+ void ORequestThread::onTerminated()
+ {
+ m_aThreadPool->getThreadAdmin().remove( this );
+ release();
+ }
+
+ void ORequestThread::run()
+ {
+ osl_setThreadName("cppu_threadpool::ORequestThread");
+
+ try
+ {
+ while ( m_pQueue )
+ {
+ if( ! m_bAsynchron )
+ {
+ if ( !uno_bindIdToCurrentThread( m_aThreadId.getHandle() ) )
+ {
+ OSL_ASSERT( false );
+ }
+ }
+
+ while( ! m_pQueue->isEmpty() )
+ {
+ // Note : Oneways should not get a disposable disposeid,
+ // It does not make sense to dispose a call in this state.
+ // That's way we put it a disposeid, that can't be used otherwise.
+ m_pQueue->enter(
+ this,
+ true );
+
+ if( m_pQueue->isEmpty() )
+ {
+ m_aThreadPool->revokeQueue( m_aThreadId , m_bAsynchron );
+ // Note : revokeQueue might have failed because m_pQueue.isEmpty()
+ // may be false (race).
+ }
+ }
+
+ delete m_pQueue;
+ m_pQueue = nullptr;
+
+ if( ! m_bAsynchron )
+ {
+ uno_releaseIdFromCurrentThread();
+ }
+
+ m_aThreadPool->waitInPool( this );
+ }
+ }
+ catch (...)
+ {
+ // Work around the problem that onTerminated is not called if run
+ // throws an exception:
+ onTerminated();
+ throw;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/threadpool/thread.hxx b/cppu/source/threadpool/thread.hxx
new file mode 100644
index 000000000..5d03de88e
--- /dev/null
+++ b/cppu/source/threadpool/thread.hxx
@@ -0,0 +1,67 @@
+/* -*- 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 .
+ */
+#pragma once
+
+#include <osl/thread.hxx>
+#include <sal/types.h>
+#include <salhelper/simplereferenceobject.hxx>
+
+#include "threadpool.hxx"
+
+namespace cppu_threadpool {
+
+ class JobQueue;
+
+
+ // private thread class for the threadpool
+
+ class ORequestThread:
+ public salhelper::SimpleReferenceObject, public osl::Thread
+ {
+ public:
+ ORequestThread( ThreadPoolHolder aThreadPool,
+ JobQueue * ,
+ ::rtl::ByteSequence aThreadId,
+ bool bAsynchron );
+ virtual ~ORequestThread() override;
+
+ void setTask( JobQueue * , const ::rtl::ByteSequence & aThreadId , bool bAsynchron );
+
+ bool launch();
+
+ static void * operator new(std::size_t size)
+ { return SimpleReferenceObject::operator new(size); }
+
+ static void operator delete(void * pointer)
+ { SimpleReferenceObject::operator delete(pointer); }
+
+ private:
+ virtual void SAL_CALL run() override;
+ virtual void SAL_CALL onTerminated() override;
+
+ ThreadPoolHolder m_aThreadPool;
+ JobQueue *m_pQueue;
+ ::rtl::ByteSequence m_aThreadId;
+ bool m_bAsynchron;
+ };
+
+} // end cppu_threadpool
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/threadpool/threadident.cxx b/cppu/source/threadpool/threadident.cxx
new file mode 100644
index 000000000..16b7c0b27
--- /dev/null
+++ b/cppu/source/threadpool/threadident.cxx
@@ -0,0 +1,120 @@
+/* -*- 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/thread.hxx>
+#include <osl/diagnose.h>
+
+#include <rtl/process.h>
+#include <rtl/byteseq.hxx>
+
+#include <uno/threadpool.h>
+
+#include "current.hxx"
+
+using namespace ::std;
+using namespace ::osl;
+using namespace ::cppu;
+
+static void createLocalId( sal_Sequence **ppThreadId )
+{
+ rtl_byte_sequence_constructNoDefault( ppThreadId , 4 + 16 );
+ sal_uInt32 id = osl::Thread::getCurrentIdentifier();
+ (*ppThreadId)->elements[0] = id & 0xFF;
+ (*ppThreadId)->elements[1] = (id >> 8) & 0xFF;
+ (*ppThreadId)->elements[2] = (id >> 16) & 0xFF;
+ (*ppThreadId)->elements[3] = (id >> 24) & 0xFF;
+ rtl_getGlobalProcessId( reinterpret_cast<sal_uInt8 *>(&(*ppThreadId)->elements[4]) );
+}
+
+extern "C" void SAL_CALL
+uno_getIdOfCurrentThread( sal_Sequence **ppThreadId )
+ SAL_THROW_EXTERN_C()
+{
+ IdContainer& id = getIdContainer();
+ if (!id.bInit)
+ {
+ // first time, that the thread enters the bridge
+ createLocalId( ppThreadId );
+
+ // TODO
+ // note : this is a leak !
+ id.pLocalThreadId = *ppThreadId;
+ id.pCurrentId = *ppThreadId;
+ id.nRefCountOfCurrentId = 1;
+ rtl_byte_sequence_acquire( id.pLocalThreadId );
+ rtl_byte_sequence_acquire( id.pCurrentId );
+ id.bInit = true;
+ }
+ else
+ {
+ id.nRefCountOfCurrentId ++;
+ if( *ppThreadId )
+ {
+ rtl_byte_sequence_release( *ppThreadId );
+ }
+ *ppThreadId = id.pCurrentId;
+ rtl_byte_sequence_acquire( *ppThreadId );
+ }
+}
+
+extern "C" void SAL_CALL uno_releaseIdFromCurrentThread()
+ SAL_THROW_EXTERN_C()
+{
+ IdContainer& id = getIdContainer();
+ OSL_ASSERT( id.bInit );
+ OSL_ASSERT( id.nRefCountOfCurrentId );
+
+ id.nRefCountOfCurrentId --;
+ if( ! id.nRefCountOfCurrentId && (id.pLocalThreadId != id.pCurrentId) )
+ {
+ rtl_byte_sequence_assign( &(id.pCurrentId) , id.pLocalThreadId );
+ }
+}
+
+extern "C" sal_Bool SAL_CALL uno_bindIdToCurrentThread( sal_Sequence *pThreadId )
+ SAL_THROW_EXTERN_C()
+{
+ IdContainer& id = getIdContainer();
+ if (!id.bInit)
+ {
+ id.pLocalThreadId = nullptr;
+ createLocalId( &(id.pLocalThreadId) );
+ id.nRefCountOfCurrentId = 1;
+ id.pCurrentId = pThreadId;
+ rtl_byte_sequence_acquire(id.pCurrentId);
+ id.bInit = true;
+ }
+ else
+ {
+ OSL_ASSERT( 0 == id.nRefCountOfCurrentId );
+ if( 0 == id.nRefCountOfCurrentId )
+ {
+ rtl_byte_sequence_assign(&( id.pCurrentId ), pThreadId );
+ id.nRefCountOfCurrentId ++;
+ }
+ else
+ {
+ return false;
+ }
+
+ }
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/threadpool/threadpool.cxx b/cppu/source/threadpool/threadpool.cxx
new file mode 100644
index 000000000..897bebed9
--- /dev/null
+++ b/cppu/source/threadpool/threadpool.cxx
@@ -0,0 +1,476 @@
+/* -*- 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 <cassert>
+#include <chrono>
+#include <algorithm>
+#include <utility>
+#include <unordered_map>
+
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+
+#include <uno/threadpool.h>
+
+#include "threadpool.hxx"
+#include "thread.hxx"
+
+using namespace ::std;
+using namespace ::osl;
+using namespace ::rtl;
+
+namespace cppu_threadpool
+{
+ WaitingThread::WaitingThread(
+ rtl::Reference<ORequestThread> theThread): thread(std::move(theThread))
+ {}
+
+ DisposedCallerAdminHolder const & DisposedCallerAdmin::getInstance()
+ {
+ static DisposedCallerAdminHolder theDisposedCallerAdmin = std::make_shared<DisposedCallerAdmin>();
+ return theDisposedCallerAdmin;
+ }
+
+ DisposedCallerAdmin::~DisposedCallerAdmin()
+ {
+ SAL_WARN_IF( !m_vector.empty(), "cppu.threadpool", "DisposedCallerList : " << m_vector.size() << " left");
+ }
+
+ void DisposedCallerAdmin::dispose( void const * nDisposeId )
+ {
+ std::scoped_lock guard( m_mutex );
+ m_vector.push_back( nDisposeId );
+ }
+
+ void DisposedCallerAdmin::destroy( void const * nDisposeId )
+ {
+ std::scoped_lock guard( m_mutex );
+ m_vector.erase(std::remove(m_vector.begin(), m_vector.end(), nDisposeId), m_vector.end());
+ }
+
+ bool DisposedCallerAdmin::isDisposed( void const * nDisposeId )
+ {
+ std::scoped_lock guard( m_mutex );
+ return (std::find(m_vector.begin(), m_vector.end(), nDisposeId) != m_vector.end());
+ }
+
+
+ ThreadPool::ThreadPool() :
+ m_DisposedCallerAdmin( DisposedCallerAdmin::getInstance() )
+ {
+ }
+
+ ThreadPool::~ThreadPool()
+ {
+ SAL_WARN_IF( m_mapQueue.size(), "cppu.threadpool", "ThreadIdHashMap: " << m_mapQueue.size() << " left");
+ }
+
+ void ThreadPool::dispose( void const * nDisposeId )
+ {
+ m_DisposedCallerAdmin->dispose( nDisposeId );
+
+ std::scoped_lock guard( m_mutex );
+ for (auto const& item : m_mapQueue)
+ {
+ if( item.second.first )
+ {
+ item.second.first->dispose( nDisposeId );
+ }
+ if( item.second.second )
+ {
+ item.second.second->dispose( nDisposeId );
+ }
+ }
+ }
+
+ void ThreadPool::destroy( void const * nDisposeId )
+ {
+ m_DisposedCallerAdmin->destroy( nDisposeId );
+ }
+
+ /******************
+ * This methods lets the thread wait a certain amount of time. If within this timespan
+ * a new request comes in, this thread is reused. This is done only to improve performance,
+ * it is not required for threadpool functionality.
+ ******************/
+ void ThreadPool::waitInPool( rtl::Reference< ORequestThread > const & pThread )
+ {
+ WaitingThread waitingThread(pThread);
+ {
+ std::scoped_lock guard( m_mutexWaitingThreadList );
+ m_dequeThreads.push_front( &waitingThread );
+ }
+
+ // let the thread wait 2 seconds
+ waitingThread.condition.wait( std::chrono::seconds(2) );
+
+ {
+ std::scoped_lock guard ( m_mutexWaitingThreadList );
+ if( waitingThread.thread.is() )
+ {
+ // thread wasn't reused, remove it from the list
+ WaitingThreadDeque::iterator ii = find(
+ m_dequeThreads.begin(), m_dequeThreads.end(), &waitingThread );
+ OSL_ASSERT( ii != m_dequeThreads.end() );
+ m_dequeThreads.erase( ii );
+ }
+ }
+ }
+
+ void ThreadPool::joinWorkers()
+ {
+ {
+ std::scoped_lock guard( m_mutexWaitingThreadList );
+ for (auto const& thread : m_dequeThreads)
+ {
+ // wake the threads up
+ thread->condition.set();
+ }
+ }
+ m_aThreadAdmin.join();
+ }
+
+ bool ThreadPool::createThread( JobQueue *pQueue ,
+ const ByteSequence &aThreadId,
+ bool bAsynchron )
+ {
+ {
+ // Can a thread be reused ?
+ std::scoped_lock guard( m_mutexWaitingThreadList );
+ if( ! m_dequeThreads.empty() )
+ {
+ // inform the thread and let it go
+ struct WaitingThread *pWaitingThread = m_dequeThreads.back();
+ pWaitingThread->thread->setTask( pQueue , aThreadId , bAsynchron );
+ pWaitingThread->thread = nullptr;
+
+ // remove from list
+ m_dequeThreads.pop_back();
+
+ // let the thread go
+ pWaitingThread->condition.set();
+ return true;
+ }
+ }
+
+ rtl::Reference pThread(
+ new ORequestThread( this, pQueue , aThreadId, bAsynchron) );
+ return pThread->launch();
+ }
+
+ bool ThreadPool::revokeQueue( const ByteSequence &aThreadId, bool bAsynchron )
+ {
+ std::scoped_lock guard( m_mutex );
+
+ ThreadIdHashMap::iterator ii = m_mapQueue.find( aThreadId );
+ OSL_ASSERT( ii != m_mapQueue.end() );
+
+ if( bAsynchron )
+ {
+ if( ! (*ii).second.second->isEmpty() )
+ {
+ // another thread has put something into the queue
+ return false;
+ }
+
+ (*ii).second.second = nullptr;
+ if( (*ii).second.first )
+ {
+ // all oneway request have been processed, now
+ // synchronous requests may go on
+ (*ii).second.first->resume();
+ }
+ }
+ else
+ {
+ if( ! (*ii).second.first->isEmpty() )
+ {
+ // another thread has put something into the queue
+ return false;
+ }
+ (*ii).second.first = nullptr;
+ }
+
+ if( nullptr == (*ii).second.first && nullptr == (*ii).second.second )
+ {
+ m_mapQueue.erase( ii );
+ }
+
+ return true;
+ }
+
+
+ bool ThreadPool::addJob(
+ const ByteSequence &aThreadId ,
+ bool bAsynchron,
+ void *pThreadSpecificData,
+ RequestFun * doRequest,
+ void const * disposeId )
+ {
+ bool bCreateThread = false;
+ JobQueue *pQueue = nullptr;
+ {
+ std::scoped_lock guard( m_mutex );
+ if (m_DisposedCallerAdmin->isDisposed(disposeId)) {
+ return true;
+ }
+
+ ThreadIdHashMap::iterator ii = m_mapQueue.find( aThreadId );
+
+ if( ii == m_mapQueue.end() )
+ {
+ m_mapQueue[ aThreadId ] = pair < JobQueue * , JobQueue * > ( nullptr , nullptr );
+ ii = m_mapQueue.find( aThreadId );
+ OSL_ASSERT( ii != m_mapQueue.end() );
+ }
+
+ if( bAsynchron )
+ {
+ if( ! (*ii).second.second )
+ {
+ (*ii).second.second = new JobQueue();
+ bCreateThread = true;
+ }
+ pQueue = (*ii).second.second;
+ }
+ else
+ {
+ if( ! (*ii).second.first )
+ {
+ (*ii).second.first = new JobQueue();
+ bCreateThread = true;
+ }
+ pQueue = (*ii).second.first;
+
+ if( (*ii).second.second && ( (*ii).second.second->isBusy() ) )
+ {
+ pQueue->suspend();
+ }
+ }
+ pQueue->add( pThreadSpecificData , doRequest );
+ }
+
+ return !bCreateThread || createThread( pQueue , aThreadId , bAsynchron);
+ }
+
+ void ThreadPool::prepare( const ByteSequence &aThreadId )
+ {
+ std::scoped_lock guard( m_mutex );
+
+ ThreadIdHashMap::iterator ii = m_mapQueue.find( aThreadId );
+
+ if( ii == m_mapQueue.end() )
+ {
+ JobQueue *p = new JobQueue();
+ m_mapQueue[ aThreadId ] = pair< JobQueue * , JobQueue * > ( p , nullptr );
+ }
+ else if( nullptr == (*ii).second.first )
+ {
+ (*ii).second.first = new JobQueue();
+ }
+ }
+
+ void * ThreadPool::enter( const ByteSequence & aThreadId , void const * nDisposeId )
+ {
+ JobQueue *pQueue = nullptr;
+ {
+ std::scoped_lock guard( m_mutex );
+
+ ThreadIdHashMap::iterator ii = m_mapQueue.find( aThreadId );
+
+ OSL_ASSERT( ii != m_mapQueue.end() );
+ pQueue = (*ii).second.first;
+ }
+
+ OSL_ASSERT( pQueue );
+ void *pReturn = pQueue->enter( nDisposeId );
+
+ if( pQueue->isCallstackEmpty() )
+ {
+ if( revokeQueue( aThreadId , false) )
+ {
+ // remove queue
+ delete pQueue;
+ }
+ }
+ return pReturn;
+ }
+}
+
+// All uno_ThreadPool handles in g_pThreadpoolHashSet with overlapping life
+// spans share one ThreadPool instance. When g_pThreadpoolHashSet becomes empty
+// (within the last uno_threadpool_destroy) all worker threads spawned by that
+// ThreadPool instance are joined (which implies that uno_threadpool_destroy
+// must never be called from a worker thread); afterwards, the next call to
+// uno_threadpool_create (if any) will lead to a new ThreadPool instance.
+
+using namespace cppu_threadpool;
+
+namespace {
+
+struct uno_ThreadPool_Equal
+{
+ bool operator () ( const uno_ThreadPool &a , const uno_ThreadPool &b ) const
+ {
+ return a == b;
+ }
+};
+
+struct uno_ThreadPool_Hash
+{
+ std::size_t operator () ( const uno_ThreadPool &a ) const
+ {
+ return reinterpret_cast<std::size_t>( a );
+ }
+};
+
+}
+
+typedef std::unordered_map< uno_ThreadPool, ThreadPoolHolder, uno_ThreadPool_Hash, uno_ThreadPool_Equal > ThreadpoolHashSet;
+
+static ThreadpoolHashSet *g_pThreadpoolHashSet;
+
+struct _uno_ThreadPool
+{
+ sal_Int32 dummy;
+};
+
+namespace {
+
+ThreadPoolHolder getThreadPool( uno_ThreadPool hPool )
+{
+ MutexGuard guard( Mutex::getGlobalMutex() );
+ assert( g_pThreadpoolHashSet != nullptr );
+ ThreadpoolHashSet::iterator i( g_pThreadpoolHashSet->find(hPool) );
+ assert( i != g_pThreadpoolHashSet->end() );
+ return i->second;
+}
+
+}
+
+extern "C" uno_ThreadPool SAL_CALL
+uno_threadpool_create() SAL_THROW_EXTERN_C()
+{
+ MutexGuard guard( Mutex::getGlobalMutex() );
+ ThreadPoolHolder p;
+ if( ! g_pThreadpoolHashSet )
+ {
+ g_pThreadpoolHashSet = new ThreadpoolHashSet;
+ p = new ThreadPool;
+ }
+ else
+ {
+ assert( !g_pThreadpoolHashSet->empty() );
+ p = g_pThreadpoolHashSet->begin()->second;
+ }
+
+ // Just ensure that the handle is unique in the process (via heap)
+ uno_ThreadPool h = new struct _uno_ThreadPool;
+ g_pThreadpoolHashSet->emplace( h, p );
+ return h;
+}
+
+extern "C" void SAL_CALL
+uno_threadpool_attach( uno_ThreadPool hPool ) SAL_THROW_EXTERN_C()
+{
+ sal_Sequence *pThreadId = nullptr;
+ uno_getIdOfCurrentThread( &pThreadId );
+ getThreadPool( hPool )->prepare( pThreadId );
+ rtl_byte_sequence_release( pThreadId );
+ uno_releaseIdFromCurrentThread();
+}
+
+extern "C" void SAL_CALL
+uno_threadpool_enter( uno_ThreadPool hPool , void **ppJob )
+ SAL_THROW_EXTERN_C()
+{
+ sal_Sequence *pThreadId = nullptr;
+ uno_getIdOfCurrentThread( &pThreadId );
+ *ppJob =
+ getThreadPool( hPool )->enter(
+ pThreadId,
+ hPool );
+ rtl_byte_sequence_release( pThreadId );
+ uno_releaseIdFromCurrentThread();
+}
+
+extern "C" void SAL_CALL
+uno_threadpool_detach(SAL_UNUSED_PARAMETER uno_ThreadPool) SAL_THROW_EXTERN_C()
+{
+ // we might do here some tidying up in case a thread called attach but never detach
+}
+
+extern "C" void SAL_CALL
+uno_threadpool_putJob(
+ uno_ThreadPool hPool,
+ sal_Sequence *pThreadId,
+ void *pJob,
+ void ( SAL_CALL * doRequest ) ( void *pThreadSpecificData ),
+ sal_Bool bIsOneway ) SAL_THROW_EXTERN_C()
+{
+ if (!getThreadPool(hPool)->addJob( pThreadId, bIsOneway, pJob ,doRequest, hPool ))
+ {
+ SAL_WARN(
+ "cppu.threadpool",
+ "uno_threadpool_putJob in parallel with uno_threadpool_destroy");
+ }
+}
+
+extern "C" void SAL_CALL
+uno_threadpool_dispose( uno_ThreadPool hPool ) SAL_THROW_EXTERN_C()
+{
+ getThreadPool(hPool)->dispose(
+ hPool );
+}
+
+extern "C" void SAL_CALL
+uno_threadpool_destroy( uno_ThreadPool hPool ) SAL_THROW_EXTERN_C()
+{
+ ThreadPoolHolder p( getThreadPool(hPool) );
+ p->destroy(
+ hPool );
+
+ bool empty;
+ {
+ OSL_ASSERT( g_pThreadpoolHashSet );
+
+ MutexGuard guard( Mutex::getGlobalMutex() );
+
+ ThreadpoolHashSet::iterator ii = g_pThreadpoolHashSet->find( hPool );
+ OSL_ASSERT( ii != g_pThreadpoolHashSet->end() );
+ g_pThreadpoolHashSet->erase( ii );
+ delete hPool;
+
+ empty = g_pThreadpoolHashSet->empty();
+ if( empty )
+ {
+ delete g_pThreadpoolHashSet;
+ g_pThreadpoolHashSet = nullptr;
+ }
+ }
+
+ if( empty )
+ {
+ p->joinWorkers();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/threadpool/threadpool.hxx b/cppu/source/threadpool/threadpool.hxx
new file mode 100644
index 000000000..afcae7a7e
--- /dev/null
+++ b/cppu/source/threadpool/threadpool.hxx
@@ -0,0 +1,162 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <mutex>
+#include <vector>
+#include <unordered_map>
+
+#include <osl/conditn.hxx>
+#include <osl/mutex.hxx>
+#include <rtl/byteseq.hxx>
+#include <rtl/ref.hxx>
+#include <salhelper/simplereferenceobject.hxx>
+
+#include "jobqueue.hxx"
+
+
+namespace cppu_threadpool {
+ class ORequestThread;
+
+ struct EqualThreadId
+ {
+ bool operator () ( const ::rtl::ByteSequence &a , const ::rtl::ByteSequence &b ) const
+ {
+ return a == b;
+ }
+ };
+
+ struct HashThreadId
+ {
+ sal_Int32 operator () ( const ::rtl::ByteSequence &a ) const
+ {
+ if( a.getLength() >= 4 )
+ {
+ return *reinterpret_cast<sal_Int32 const *>(a.getConstArray());
+ }
+ return 0;
+ }
+ };
+
+ typedef std::unordered_map
+ <
+ ::rtl::ByteSequence, // ThreadID
+ std::pair < JobQueue * , JobQueue * >,
+ HashThreadId,
+ EqualThreadId
+ > ThreadIdHashMap;
+
+ struct WaitingThread
+ {
+ osl::Condition condition;
+ rtl::Reference< ORequestThread > thread;
+
+ explicit WaitingThread(
+ rtl::Reference<ORequestThread> theThread);
+ };
+
+ typedef std::deque< struct ::cppu_threadpool::WaitingThread * > WaitingThreadDeque;
+
+ class DisposedCallerAdmin;
+ typedef std::shared_ptr<DisposedCallerAdmin> DisposedCallerAdminHolder;
+
+ class DisposedCallerAdmin
+ {
+ public:
+ ~DisposedCallerAdmin();
+
+ static DisposedCallerAdminHolder const & getInstance();
+
+ void dispose( void const * nDisposeId );
+ void destroy( void const * nDisposeId );
+ bool isDisposed( void const * nDisposeId );
+
+ private:
+ std::mutex m_mutex;
+ std::vector< void const * > m_vector;
+ };
+
+ class ThreadAdmin
+ {
+ public:
+ ThreadAdmin();
+ ~ThreadAdmin ();
+
+ void remove( rtl::Reference< ORequestThread > const & );
+ void join();
+
+ bool add_locked( rtl::Reference< ORequestThread > const & );
+ void remove_locked( rtl::Reference< ORequestThread > const & );
+ std::mutex m_mutex;
+
+ private:
+ std::deque< rtl::Reference< ORequestThread > > m_deque;
+ bool m_disposed;
+ };
+
+ class ThreadPool;
+ typedef rtl::Reference<ThreadPool> ThreadPoolHolder;
+
+ class ThreadPool: public salhelper::SimpleReferenceObject
+ {
+ public:
+ ThreadPool();
+ virtual ~ThreadPool() override;
+
+ void dispose( void const * nDisposeId );
+ void destroy( void const * nDisposeId );
+
+ bool addJob( const ::rtl::ByteSequence &aThreadId,
+ bool bAsynchron,
+ void *pThreadSpecificData,
+ RequestFun * doRequest,
+ void const * disposeId );
+
+ void prepare( const ::rtl::ByteSequence &aThreadId );
+ void * enter( const ::rtl::ByteSequence &aThreadId, void const * nDisposeId );
+
+ /********
+ * @return true, if queue could be successfully revoked.
+ ********/
+ bool revokeQueue( const ::rtl::ByteSequence & aThreadId , bool bAsynchron );
+
+ void waitInPool( rtl::Reference< ORequestThread > const & pThread );
+
+ void joinWorkers();
+
+ ThreadAdmin & getThreadAdmin() { return m_aThreadAdmin; }
+
+ private:
+ bool createThread( JobQueue *pQueue, const ::rtl::ByteSequence &aThreadId, bool bAsynchron);
+
+
+ ThreadIdHashMap m_mapQueue;
+ std::mutex m_mutex;
+
+ std::mutex m_mutexWaitingThreadList;
+ WaitingThreadDeque m_dequeThreads;
+
+ DisposedCallerAdminHolder m_DisposedCallerAdmin;
+ ThreadAdmin m_aThreadAdmin;
+ };
+
+} // end namespace cppu_threadpool
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/typelib/static_types.cxx b/cppu/source/typelib/static_types.cxx
new file mode 100644
index 000000000..6b9a35ac9
--- /dev/null
+++ b/cppu/source/typelib/static_types.cxx
@@ -0,0 +1,555 @@
+/* -*- 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 <algorithm>
+#include <cassert>
+
+#include <osl/mutex.hxx>
+#include <rtl/ustring.hxx>
+
+#include <typelib/typedescription.h>
+#include "typelib.hxx"
+
+
+using namespace osl;
+
+namespace
+{
+ Mutex& typelib_StaticInitMutex()
+ {
+ static Mutex SINGLETON;
+ return SINGLETON;
+ }
+}
+
+extern "C"
+{
+
+
+#ifdef _WIN32
+#pragma pack(push, 8)
+#endif
+
+namespace {
+
+/**
+ * The double member determines the alignment.
+ * Under OS2 and MS-Windows the Alignment is min( 8, sizeof( type ) ).
+ * The alignment of a structure is min( 8, sizeof( max basic type ) ), the greatest basic type
+ * determines the alignment.
+ */
+struct AlignSize_Impl
+{
+ sal_Int16 nInt16;
+#ifdef AIX
+ //double: doubleword aligned if -qalign=natural/-malign=natural
+ //which isn't the default ABI. Otherwise word aligned, While a long long int
+ //is always doubleword aligned, so use that instead.
+ sal_Int64 dDouble;
+#else
+ double dDouble;
+#endif
+};
+
+}
+
+#ifdef _WIN32
+#pragma pack(pop)
+#endif
+
+// the value of the maximal alignment
+const sal_Int32 nMaxAlignment = static_cast<sal_Int32>( reinterpret_cast<sal_Size>(&reinterpret_cast<AlignSize_Impl *>(16)->dDouble) - 16);
+
+static sal_Int32 adjustAlignment( sal_Int32 nRequestedAlignment )
+{
+ if( nRequestedAlignment > nMaxAlignment )
+ nRequestedAlignment = nMaxAlignment;
+ return nRequestedAlignment;
+}
+
+/**
+ * Calculate the new size of the struktur.
+ */
+static sal_Int32 newAlignedSize(
+ sal_Int32 OldSize, sal_Int32 ElementSize, sal_Int32 NeededAlignment )
+{
+ NeededAlignment = adjustAlignment( NeededAlignment );
+ return (OldSize + NeededAlignment -1) / NeededAlignment * NeededAlignment + ElementSize;
+}
+
+
+// !for NOT REALLY WEAK TYPES only!
+static typelib_TypeDescriptionReference * igetTypeByName( rtl_uString const * pTypeName )
+{
+ typelib_TypeDescriptionReference * pRef = nullptr;
+ ::typelib_typedescriptionreference_getByName( &pRef, pTypeName );
+ if (pRef && pRef->pType && pRef->pType->pWeakRef) // found initialized td
+ {
+ return pRef;
+ }
+ return nullptr;
+}
+
+extern "C"
+{
+
+typelib_TypeDescriptionReference ** SAL_CALL typelib_static_type_getByTypeClass(
+ typelib_TypeClass eTypeClass )
+ SAL_THROW_EXTERN_C()
+{
+ static typelib_TypeDescriptionReference * s_aTypes[] = {
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr };
+
+ if (! s_aTypes[eTypeClass])
+ {
+ MutexGuard aGuard( typelib_StaticInitMutex() );
+ if (! s_aTypes[eTypeClass])
+ {
+ static const char * s_aTypeNames[] = {
+ "void", "char", "boolean", "byte",
+ "short", "unsigned short", "long", "unsigned long",
+ "hyper", "unsigned hyper", "float", "double",
+ "string", "type", "any" };
+
+ switch (eTypeClass)
+ {
+ case typelib_TypeClass_EXCEPTION:
+ case typelib_TypeClass_INTERFACE:
+ {
+ // type
+ if (! s_aTypes[typelib_TypeClass_TYPE])
+ {
+ OUString sTypeName("type");
+ ::typelib_typedescriptionreference_new(
+ &s_aTypes[typelib_TypeClass_TYPE], typelib_TypeClass_TYPE, sTypeName.pData );
+ // another static ref:
+ ++s_aTypes[typelib_TypeClass_TYPE]->nStaticRefCount;
+ }
+ // any
+ if (! s_aTypes[typelib_TypeClass_ANY])
+ {
+ OUString sTypeName("any");
+ ::typelib_typedescriptionreference_new(
+ &s_aTypes[typelib_TypeClass_ANY], typelib_TypeClass_ANY, sTypeName.pData );
+ // another static ref:
+ ++s_aTypes[typelib_TypeClass_ANY]->nStaticRefCount;
+ }
+ // string
+ if (! s_aTypes[typelib_TypeClass_STRING])
+ {
+ OUString sTypeName("string");
+ ::typelib_typedescriptionreference_new(
+ &s_aTypes[typelib_TypeClass_STRING], typelib_TypeClass_STRING, sTypeName.pData );
+ // another static ref:
+ ++s_aTypes[typelib_TypeClass_STRING]->nStaticRefCount;
+ }
+ // XInterface
+ if (! s_aTypes[typelib_TypeClass_INTERFACE])
+ {
+ OUString sTypeName("com.sun.star.uno.XInterface");
+
+ typelib_InterfaceTypeDescription * pTD = nullptr;
+
+ typelib_TypeDescriptionReference * pMembers[3] = { nullptr,nullptr,nullptr };
+ OUString sMethodName0("com.sun.star.uno.XInterface::queryInterface");
+ ::typelib_typedescriptionreference_new(
+ &pMembers[0], typelib_TypeClass_INTERFACE_METHOD, sMethodName0.pData );
+ OUString sMethodName1("com.sun.star.uno.XInterface::acquire");
+ ::typelib_typedescriptionreference_new(
+ &pMembers[1], typelib_TypeClass_INTERFACE_METHOD, sMethodName1.pData );
+ OUString sMethodName2("com.sun.star.uno.XInterface::release");
+ ::typelib_typedescriptionreference_new(
+ &pMembers[2], typelib_TypeClass_INTERFACE_METHOD, sMethodName2.pData );
+
+ ::typelib_typedescription_newInterface(
+ &pTD, sTypeName.pData, 0, 0, 0, 0, 0, nullptr, 3, pMembers );
+
+ ::typelib_typedescription_register( reinterpret_cast<typelib_TypeDescription **>(&pTD) );
+ s_aTypes[typelib_TypeClass_INTERFACE] = pTD->aBase.pWeakRef;
+ ::typelib_typedescriptionreference_acquire(
+ s_aTypes[typelib_TypeClass_INTERFACE] );
+ // another static ref:
+ ++s_aTypes[typelib_TypeClass_INTERFACE]->nStaticRefCount;
+ ::typelib_typedescription_release( &pTD->aBase );
+
+ ::typelib_typedescriptionreference_release( pMembers[0] );
+ ::typelib_typedescriptionreference_release( pMembers[1] );
+ ::typelib_typedescriptionreference_release( pMembers[2] );
+ // Exception
+ assert( ! s_aTypes[typelib_TypeClass_EXCEPTION] );
+ {
+ typelib_TypeDescription * pTD1 = nullptr;
+ OUString sTypeName1("com.sun.star.uno.Exception");
+
+ typelib_CompoundMember_Init aMembers[2];
+ OUString sMemberType0("string");
+ OUString sMemberName0("Message");
+ aMembers[0].eTypeClass = typelib_TypeClass_STRING;
+ aMembers[0].pTypeName = sMemberType0.pData;
+ aMembers[0].pMemberName = sMemberName0.pData;
+ OUString sMemberType1("com.sun.star.uno.XInterface");
+ OUString sMemberName1("Context");
+ aMembers[1].eTypeClass = typelib_TypeClass_INTERFACE;
+ aMembers[1].pTypeName = sMemberType1.pData;
+ aMembers[1].pMemberName = sMemberName1.pData;
+
+ ::typelib_typedescription_new(
+ &pTD1, typelib_TypeClass_EXCEPTION, sTypeName1.pData, nullptr, 2, aMembers );
+ typelib_typedescription_register( &pTD1 );
+ s_aTypes[typelib_TypeClass_EXCEPTION] = pTD1->pWeakRef;
+ typelib_typedescriptionreference_acquire(
+ s_aTypes[typelib_TypeClass_EXCEPTION]);
+ // another static ref:
+ ++s_aTypes[typelib_TypeClass_EXCEPTION]->nStaticRefCount;
+ // RuntimeException
+ OUString sTypeName2("com.sun.star.uno.RuntimeException");
+ ::typelib_typedescription_new(
+ &pTD1, typelib_TypeClass_EXCEPTION, sTypeName2.pData, s_aTypes[typelib_TypeClass_EXCEPTION], 0, nullptr );
+ ::typelib_typedescription_register( &pTD1 );
+ ::typelib_typedescription_release( pTD1 );
+ }
+ // XInterface members
+ typelib_InterfaceMethodTypeDescription * pMethod = nullptr;
+ typelib_Parameter_Init aParameters[1];
+ OUString sParamName0("aType");
+ OUString sParamType0("type");
+ aParameters[0].pParamName = sParamName0.pData;
+ aParameters[0].eTypeClass = typelib_TypeClass_TYPE;
+ aParameters[0].pTypeName = sParamType0.pData;
+ aParameters[0].bIn = true;
+ aParameters[0].bOut = false;
+ rtl_uString * pExceptions[1];
+ OUString sExceptionName0("com.sun.star.uno.RuntimeException");
+ pExceptions[0] = sExceptionName0.pData;
+ OUString sReturnType0("any");
+ typelib_typedescription_newInterfaceMethod(
+ &pMethod, 0, false, sMethodName0.pData,
+ typelib_TypeClass_ANY, sReturnType0.pData,
+ 1, aParameters, 1, pExceptions );
+ ::typelib_typedescription_register( reinterpret_cast<typelib_TypeDescription**>(&pMethod) );
+
+ OUString sReturnType1("void");
+ ::typelib_typedescription_newInterfaceMethod(
+ &pMethod, 1, true, sMethodName1.pData,
+ typelib_TypeClass_VOID, sReturnType1.pData, 0, nullptr, 0, nullptr );
+ ::typelib_typedescription_register( reinterpret_cast<typelib_TypeDescription**>(&pMethod) );
+
+ ::typelib_typedescription_newInterfaceMethod(
+ &pMethod, 2, true, sMethodName2.pData,
+ typelib_TypeClass_VOID, sReturnType1.pData,
+ 0, nullptr, 0, nullptr );
+ ::typelib_typedescription_register( reinterpret_cast<typelib_TypeDescription**>(&pMethod) );
+ ::typelib_typedescription_release( &pMethod->aBase.aBase );
+ }
+ break;
+ }
+ default:
+ {
+ OUString aTypeName( OUString::createFromAscii( s_aTypeNames[eTypeClass] ) );
+ ::typelib_typedescriptionreference_new( &s_aTypes[eTypeClass], eTypeClass, aTypeName.pData );
+ // another static ref:
+ ++s_aTypes[eTypeClass]->nStaticRefCount;
+ }
+ }
+ }
+ }
+ return &s_aTypes[eTypeClass];
+}
+
+void SAL_CALL typelib_static_type_init(
+ typelib_TypeDescriptionReference ** ppRef,
+ typelib_TypeClass eTypeClass, const char * pTypeName )
+ SAL_THROW_EXTERN_C()
+{
+ if (! *ppRef)
+ {
+ MutexGuard aGuard( typelib_StaticInitMutex() );
+ if (! *ppRef)
+ {
+ OUString aTypeName( OUString::createFromAscii( pTypeName ) );
+ ::typelib_typedescriptionreference_new( ppRef, eTypeClass, aTypeName.pData );
+
+ assert(*ppRef && "coverity[var_deref_op] - shouldn't be possible");
+ ++((*ppRef)->nStaticRefCount);
+ }
+ }
+}
+
+void SAL_CALL typelib_static_sequence_type_init(
+ typelib_TypeDescriptionReference ** ppRef,
+ typelib_TypeDescriptionReference * pElementType )
+ SAL_THROW_EXTERN_C()
+{
+ if ( *ppRef)
+ return;
+
+ MutexGuard aGuard( typelib_StaticInitMutex() );
+ if ( *ppRef)
+ return;
+
+ OUString aTypeName = "[]" + OUString::unacquired(&pElementType->pTypeName);
+
+ static_assert( ! TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK(typelib_TypeClass_SEQUENCE) );
+ *ppRef = igetTypeByName( aTypeName.pData );
+ if (!*ppRef)
+ {
+ typelib_TypeDescription * pReg = nullptr;
+ ::typelib_typedescription_new(
+ &pReg, typelib_TypeClass_SEQUENCE,
+ aTypeName.pData, pElementType, 0, nullptr );
+
+ ::typelib_typedescription_register( &pReg );
+ *ppRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg);
+ assert( *ppRef == pReg->pWeakRef );
+ }
+ // another static ref:
+ ++((*ppRef)->nStaticRefCount);
+}
+
+
+namespace {
+
+void init(
+ typelib_TypeDescriptionReference ** ppRef,
+ typelib_TypeClass eTypeClass, const char * pTypeName,
+ typelib_TypeDescriptionReference * pBaseType,
+ sal_Int32 nMembers, typelib_TypeDescriptionReference ** ppMembers,
+ sal_Bool const * pParameterizedTypes)
+{
+ assert( eTypeClass == typelib_TypeClass_STRUCT || eTypeClass == typelib_TypeClass_EXCEPTION );
+
+ if ( *ppRef)
+ return;
+
+ MutexGuard aGuard( typelib_StaticInitMutex() );
+ if ( *ppRef)
+ return;
+
+ assert( ! TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK(eTypeClass) );
+ OUString aTypeName( OUString::createFromAscii( pTypeName ) );
+ *ppRef = igetTypeByName( aTypeName.pData );
+ if (!*ppRef)
+ {
+ typelib_CompoundTypeDescription * pComp = nullptr;
+ ::typelib_typedescription_newEmpty(
+ reinterpret_cast<typelib_TypeDescription **>(&pComp), eTypeClass, aTypeName.pData );
+
+ sal_Int32 nOffset = 0;
+ if (pBaseType)
+ {
+ ::typelib_typedescriptionreference_getDescription(
+ reinterpret_cast<typelib_TypeDescription **>(&pComp->pBaseTypeDescription), pBaseType );
+ assert( pComp->pBaseTypeDescription );
+ nOffset = pComp->pBaseTypeDescription->aBase.nSize;
+ assert( newAlignedSize( 0, pComp->pBaseTypeDescription->aBase.nSize, pComp->pBaseTypeDescription->aBase.nAlignment ) == pComp->pBaseTypeDescription->aBase.nSize ); // unexpected offset
+ }
+
+ if (nMembers)
+ {
+ pComp->nMembers = nMembers;
+ pComp->pMemberOffsets = new sal_Int32[ nMembers ];
+ pComp->ppTypeRefs = new typelib_TypeDescriptionReference *[ nMembers ];
+ if (pParameterizedTypes != nullptr) {
+ reinterpret_cast< typelib_StructTypeDescription * >(
+ pComp)->pParameterizedTypes
+ = new sal_Bool[nMembers];
+ }
+ for ( sal_Int32 i = 0 ; i < nMembers; ++i )
+ {
+ pComp->ppTypeRefs[i] = ppMembers[i];
+ ::typelib_typedescriptionreference_acquire(
+ pComp->ppTypeRefs[i] );
+ // write offset
+ typelib_TypeDescription * pTD = nullptr;
+ TYPELIB_DANGER_GET( &pTD, pComp->ppTypeRefs[i] );
+ assert( pTD->nSize ); // void member?
+ nOffset = newAlignedSize( nOffset, pTD->nSize, pTD->nAlignment );
+ pComp->pMemberOffsets[i] = nOffset - pTD->nSize;
+ TYPELIB_DANGER_RELEASE( pTD );
+
+ if (pParameterizedTypes != nullptr) {
+ reinterpret_cast< typelib_StructTypeDescription * >(
+ pComp)->pParameterizedTypes[i]
+ = pParameterizedTypes[i];
+ }
+ }
+ }
+
+ typelib_TypeDescription * pReg = &pComp->aBase;
+ pReg->pWeakRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg);
+ // sizeof(void) not allowed
+ pReg->nSize = ::typelib_typedescription_getAlignedUnoSize( pReg, 0, pReg->nAlignment );
+ pReg->nAlignment = adjustAlignment( pReg->nAlignment );
+ pReg->bComplete = false;
+
+ ::typelib_typedescription_register( &pReg );
+ *ppRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg);
+ assert( *ppRef == pReg->pWeakRef );
+ }
+ // another static ref:
+ ++((*ppRef)->nStaticRefCount);
+}
+
+}
+
+void SAL_CALL typelib_static_compound_type_init(
+ typelib_TypeDescriptionReference ** ppRef,
+ typelib_TypeClass eTypeClass, const char * pTypeName,
+ typelib_TypeDescriptionReference * pBaseType,
+ sal_Int32 nMembers, typelib_TypeDescriptionReference ** ppMembers )
+ SAL_THROW_EXTERN_C()
+{
+ init(ppRef, eTypeClass, pTypeName, pBaseType, nMembers, ppMembers, nullptr);
+}
+
+void SAL_CALL typelib_static_struct_type_init(
+ typelib_TypeDescriptionReference ** ppRef, const char * pTypeName,
+ typelib_TypeDescriptionReference * pBaseType,
+ sal_Int32 nMembers, typelib_TypeDescriptionReference ** ppMembers,
+ sal_Bool const * pParameterizedTypes )
+ SAL_THROW_EXTERN_C()
+{
+ init(
+ ppRef, typelib_TypeClass_STRUCT, pTypeName, pBaseType, nMembers,
+ ppMembers, pParameterizedTypes);
+}
+
+void SAL_CALL typelib_static_interface_type_init(
+ typelib_TypeDescriptionReference ** ppRef,
+ const char * pTypeName,
+ typelib_TypeDescriptionReference * pBaseType )
+ SAL_THROW_EXTERN_C()
+{
+ // coverity[callee_ptr_arith] - not a bug
+ typelib_static_mi_interface_type_init(
+ ppRef, pTypeName, pBaseType == nullptr ? 0 : 1, &pBaseType);
+}
+
+void SAL_CALL typelib_static_mi_interface_type_init(
+ typelib_TypeDescriptionReference ** ppRef,
+ const char * pTypeName,
+ sal_Int32 nBaseTypes,
+ typelib_TypeDescriptionReference ** ppBaseTypes )
+ SAL_THROW_EXTERN_C()
+{
+ if ( *ppRef)
+ return;
+
+ MutexGuard aGuard( typelib_StaticInitMutex() );
+ if ( *ppRef)
+ return;
+
+ static_assert( ! TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK(typelib_TypeClass_INTERFACE) );
+ OUString aTypeName( OUString::createFromAscii( pTypeName ) );
+ *ppRef = igetTypeByName( aTypeName.pData );
+ if (!*ppRef)
+ {
+ typelib_InterfaceTypeDescription * pIface = nullptr;
+ ::typelib_typedescription_newEmpty(
+ reinterpret_cast<typelib_TypeDescription **>(&pIface), typelib_TypeClass_INTERFACE, aTypeName.pData );
+
+ pIface->nBaseTypes = std::max< sal_Int32 >(nBaseTypes, 1);
+ pIface->ppBaseTypes = new typelib_InterfaceTypeDescription *[
+ pIface->nBaseTypes];
+ if (nBaseTypes > 0)
+ {
+ for (sal_Int32 i = 0; i < nBaseTypes; ++i) {
+ pIface->ppBaseTypes[i] = nullptr;
+ ::typelib_typedescriptionreference_getDescription(
+ reinterpret_cast<typelib_TypeDescription **>(&pIface->ppBaseTypes[i]), ppBaseTypes[i] );
+ assert( pIface->ppBaseTypes[i] );
+ }
+ }
+ else
+ {
+ pIface->ppBaseTypes[0] = nullptr;
+ ::typelib_typedescriptionreference_getDescription(
+ reinterpret_cast<typelib_TypeDescription **>(&pIface->ppBaseTypes[0]),
+ * ::typelib_static_type_getByTypeClass( typelib_TypeClass_INTERFACE ) );
+ assert( pIface->ppBaseTypes[0] );
+ }
+ pIface->pBaseTypeDescription = pIface->ppBaseTypes[0];
+ typelib_typedescription_acquire(
+ &pIface->pBaseTypeDescription->aBase);
+
+ typelib_TypeDescription * pReg = &pIface->aBase;
+ pReg->pWeakRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg);
+ // sizeof(void) not allowed
+ pReg->nSize = ::typelib_typedescription_getAlignedUnoSize( pReg, 0, pReg->nAlignment );
+
+ pReg->nAlignment = adjustAlignment( pReg->nAlignment );
+ pReg->bComplete = false;
+
+ ::typelib_typedescription_register( &pReg );
+ *ppRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg);
+ assert( *ppRef == pReg->pWeakRef );
+ }
+ // another static ref:
+ ++((*ppRef)->nStaticRefCount);
+}
+
+
+void SAL_CALL typelib_static_enum_type_init(
+ typelib_TypeDescriptionReference ** ppRef,
+ const char * pTypeName,
+ sal_Int32 nDefaultValue )
+ SAL_THROW_EXTERN_C()
+{
+ if ( *ppRef)
+ return;
+
+ MutexGuard aGuard( typelib_StaticInitMutex() );
+ if ( *ppRef)
+ return;
+
+ static_assert( ! TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK(typelib_TypeClass_ENUM) );
+ OUString aTypeName( OUString::createFromAscii( pTypeName ) );
+ *ppRef = igetTypeByName( aTypeName.pData );
+ if (!*ppRef)
+ {
+ typelib_TypeDescription * pReg = nullptr;
+ ::typelib_typedescription_newEmpty(
+ &pReg, typelib_TypeClass_ENUM, aTypeName.pData );
+ typelib_EnumTypeDescription * pEnum = reinterpret_cast<typelib_EnumTypeDescription *>(pReg);
+
+ pEnum->nDefaultEnumValue = nDefaultValue;
+
+ pReg->pWeakRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg);
+ // sizeof(void) not allowed
+ pReg->nSize = ::typelib_typedescription_getAlignedUnoSize( pReg, 0, pReg->nAlignment );
+ pReg->nAlignment = ::adjustAlignment( pReg->nAlignment );
+ pReg->bComplete = false;
+
+ ::typelib_typedescription_register( &pReg );
+ *ppRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg);
+ assert( *ppRef == pReg->pWeakRef );
+ }
+ // another static ref:
+ ++((*ppRef)->nStaticRefCount);
+}
+
+} // extern "C"
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/typelib/typelib.cxx b/cppu/source/typelib/typelib.cxx
new file mode 100644
index 000000000..293b4e324
--- /dev/null
+++ b/cppu/source/typelib/typelib.cxx
@@ -0,0 +1,2399 @@
+/* -*- 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 <algorithm>
+#include <unordered_map>
+#include <cassert>
+#include <list>
+#include <set>
+#include <utility>
+#include <vector>
+
+#include <stdlib.h>
+#include <string.h>
+#include <sal/log.hxx>
+#include <osl/interlck.h>
+#include <osl/mutex.hxx>
+#include <rtl/ustring.hxx>
+#include <osl/diagnose.h>
+#include <typelib/typedescription.h>
+#include <uno/any2.h>
+#include <o3tl/string_view.hxx>
+#include "typelib.hxx"
+
+using namespace osl;
+
+#ifdef _WIN32
+#pragma pack(push, 8)
+#endif
+
+namespace {
+
+/**
+ * The double member determines the alignment.
+ * Under OS2 and MS-Windows the Alignment is min( 8, sizeof( type ) ).
+ * The alignment of a structure is min( 8, sizeof( max basic type ) ), the greatest basic type
+ * determines the alignment.
+ */
+struct AlignSize_Impl
+{
+ sal_Int16 nInt16;
+#ifdef AIX
+ //double: doubleword aligned if -qalign=natural/-malign=natural
+ //which isn't the default ABI. Otherwise word aligned, While a long long int
+ //is always doubleword aligned, so use that instead.
+ sal_Int64 dDouble;
+#else
+ double dDouble;
+#endif
+};
+
+}
+
+#ifdef _WIN32
+#pragma pack(pop)
+#endif
+
+// the value of the maximal alignment
+const sal_Int32 nMaxAlignment = static_cast<sal_Int32>( reinterpret_cast<sal_Size>(&reinterpret_cast<AlignSize_Impl *>(16)->dDouble) - 16);
+
+static sal_Int32 adjustAlignment( sal_Int32 nRequestedAlignment )
+{
+ if( nRequestedAlignment > nMaxAlignment )
+ nRequestedAlignment = nMaxAlignment;
+ return nRequestedAlignment;
+}
+
+/**
+ * Calculate the new size of the structure.
+ */
+static sal_Int32 newAlignedSize(
+ sal_Int32 OldSize, sal_Int32 ElementSize, sal_Int32 NeededAlignment )
+{
+ NeededAlignment = adjustAlignment( NeededAlignment );
+ return (OldSize + NeededAlignment -1) / NeededAlignment * NeededAlignment + ElementSize;
+}
+
+static sal_Int32 getDescriptionSize( typelib_TypeClass eTypeClass )
+{
+ OSL_ASSERT( typelib_TypeClass_TYPEDEF != eTypeClass );
+
+ sal_Int32 nSize;
+ // The reference is the description
+ // if the description is empty, then it must be filled with
+ // the new description
+ switch( eTypeClass )
+ {
+ case typelib_TypeClass_SEQUENCE:
+ nSize = sal_Int32(sizeof( typelib_IndirectTypeDescription ));
+ break;
+
+ case typelib_TypeClass_STRUCT:
+ nSize = sal_Int32(sizeof( typelib_StructTypeDescription ));
+ break;
+
+ case typelib_TypeClass_EXCEPTION:
+ nSize = sal_Int32(sizeof( typelib_CompoundTypeDescription ));
+ break;
+
+ case typelib_TypeClass_ENUM:
+ nSize = sal_Int32(sizeof( typelib_EnumTypeDescription ));
+ break;
+
+ case typelib_TypeClass_INTERFACE:
+ nSize = sal_Int32(sizeof( typelib_InterfaceTypeDescription ));
+ break;
+
+ case typelib_TypeClass_INTERFACE_METHOD:
+ nSize = sal_Int32(sizeof( typelib_InterfaceMethodTypeDescription ));
+ break;
+
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ nSize = sal_Int32(sizeof( typelib_InterfaceAttributeTypeDescription ));
+ break;
+
+ default:
+ nSize = sal_Int32(sizeof( typelib_TypeDescription ));
+ }
+ return nSize;
+}
+
+namespace {
+
+struct equalStr_Impl
+{
+ bool operator()(const sal_Unicode * const & s1, const sal_Unicode * const & s2) const
+ { return 0 == rtl_ustr_compare( s1, s2 ); }
+};
+
+
+struct hashStr_Impl
+{
+ size_t operator()(const sal_Unicode * const & s) const
+ { return rtl_ustr_hashCode( s ); }
+};
+
+}
+
+// Heavy hack, the const sal_Unicode * is hold by the typedescription reference
+typedef std::unordered_map< const sal_Unicode *, typelib_TypeDescriptionReference *,
+ hashStr_Impl, equalStr_Impl > WeakMap_Impl;
+
+typedef std::pair< void *, typelib_typedescription_Callback > CallbackEntry;
+typedef std::list< CallbackEntry > CallbackSet_Impl;
+typedef std::list< typelib_TypeDescription * > TypeDescriptionList_Impl;
+
+// # of cached elements
+constexpr auto nCacheSize = 256;
+
+namespace {
+
+struct TypeDescriptor_Init_Impl
+{
+ // all type description references
+ WeakMap_Impl maWeakMap;
+ // all type description callbacks
+ CallbackSet_Impl maCallbacks;
+ // A cache to hold descriptions
+ TypeDescriptionList_Impl maCache;
+ // The mutex to guard all type library accesses
+ Mutex maMutex;
+
+ inline void callChain( typelib_TypeDescription ** ppRet, rtl_uString * pName );
+
+#if OSL_DEBUG_LEVEL > 0
+ // only for debugging
+ sal_Int32 nTypeDescriptionCount = 0;
+ sal_Int32 nCompoundTypeDescriptionCount = 0;
+ sal_Int32 nIndirectTypeDescriptionCount = 0;
+ sal_Int32 nEnumTypeDescriptionCount = 0;
+ sal_Int32 nInterfaceMethodTypeDescriptionCount = 0;
+ sal_Int32 nInterfaceAttributeTypeDescriptionCount = 0;
+ sal_Int32 nInterfaceTypeDescriptionCount = 0;
+ sal_Int32 nTypeDescriptionReferenceCount = 0;
+#endif
+
+ TypeDescriptor_Init_Impl() = default;
+
+ ~TypeDescriptor_Init_Impl();
+};
+
+}
+
+inline void TypeDescriptor_Init_Impl::callChain(
+ typelib_TypeDescription ** ppRet, rtl_uString * pName )
+{
+ assert(ppRet != nullptr);
+ assert(*ppRet == nullptr);
+ for( const CallbackEntry & rEntry : maCallbacks )
+ {
+ (*rEntry.second)( rEntry.first, ppRet, pName );
+ if( *ppRet )
+ return;
+ }
+}
+
+
+TypeDescriptor_Init_Impl::~TypeDescriptor_Init_Impl()
+{
+ for( typelib_TypeDescription* pItem : maCache )
+ {
+ typelib_typedescription_release( pItem );
+ }
+
+ {
+ std::vector< typelib_TypeDescriptionReference * > ppTDR;
+ ppTDR.reserve( maWeakMap.size() );
+
+ // save all weak references
+ for( const auto& rEntry : maWeakMap )
+ {
+ ppTDR.push_back( rEntry.second );
+ typelib_typedescriptionreference_acquire( ppTDR.back() );
+ }
+
+ for( typelib_TypeDescriptionReference * pTDR : ppTDR )
+ {
+ OSL_ASSERT( pTDR->nRefCount > pTDR->nStaticRefCount );
+ pTDR->nRefCount -= pTDR->nStaticRefCount;
+
+ if( pTDR->pType && !pTDR->pType->bOnDemand )
+ {
+ pTDR->pType->bOnDemand = true;
+ typelib_typedescription_release( pTDR->pType );
+ }
+ typelib_typedescriptionreference_release( pTDR );
+ }
+
+#if defined SAL_LOG_INFO
+ for( const auto& rEntry : maWeakMap )
+ {
+ typelib_TypeDescriptionReference * pTDR = rEntry.second;
+ if (pTDR)
+ {
+ OString aTypeName( OUStringToOString( OUString::unacquired(&pTDR->pTypeName), RTL_TEXTENCODING_ASCII_US ) );
+ SAL_INFO("cppu.typelib", "remaining type: " << aTypeName << "; ref count = " << pTDR->nRefCount);
+ }
+ else
+ {
+ SAL_INFO("cppu.typelib", "remaining null type entry!?");
+ }
+ }
+#endif
+ }
+#if OSL_DEBUG_LEVEL > 0
+ SAL_INFO_IF( nTypeDescriptionCount, "cppu.typelib", "nTypeDescriptionCount is not zero" );
+ SAL_INFO_IF( nCompoundTypeDescriptionCount, "cppu.typelib", "nCompoundTypeDescriptionCount is not zero" );
+ SAL_INFO_IF( nIndirectTypeDescriptionCount, "cppu.typelib", "nIndirectTypeDescriptionCount is not zero" );
+ SAL_INFO_IF( nEnumTypeDescriptionCount, "cppu.typelib", "nEnumTypeDescriptionCount is not zero" );
+ SAL_INFO_IF( nInterfaceMethodTypeDescriptionCount, "cppu.typelib", "nInterfaceMethodTypeDescriptionCount is not zero" );
+ SAL_INFO_IF( nInterfaceAttributeTypeDescriptionCount, "cppu.typelib", "nInterfaceAttributeTypeDescriptionCount is not zero" );
+ SAL_INFO_IF( nInterfaceTypeDescriptionCount, "cppu.typelib", "nInterfaceTypeDescriptionCount is not zero" );
+ SAL_INFO_IF( nTypeDescriptionReferenceCount, "cppu.typelib", "nTypeDescriptionReferenceCount is not zero" );
+#endif
+
+ SAL_INFO_IF( !maCallbacks.empty(), "cppu.typelib", "pCallbacks is not NULL or empty" );
+};
+
+namespace {
+TypeDescriptor_Init_Impl& Init()
+{
+ static TypeDescriptor_Init_Impl SINGLETON;
+ return SINGLETON;
+}
+}
+
+extern "C" void SAL_CALL typelib_typedescription_registerCallback(
+ void * pContext, typelib_typedescription_Callback pCallback )
+ SAL_THROW_EXTERN_C()
+{
+ // todo mt safe: guard is no solution, can not acquire while calling callback!
+ TypeDescriptor_Init_Impl &rInit = Init();
+// OslGuard aGuard( rInit.getMutex() );
+ rInit.maCallbacks.push_back( CallbackEntry( pContext, pCallback ) );
+}
+
+
+extern "C" void SAL_CALL typelib_typedescription_revokeCallback(
+ void * pContext, typelib_typedescription_Callback pCallback )
+ SAL_THROW_EXTERN_C()
+{
+ TypeDescriptor_Init_Impl &rInit = Init();
+ {
+ // todo mt safe: guard is no solution, can not acquire while calling callback!
+// OslGuard aGuard( rInit.getMutex() );
+ CallbackEntry aEntry( pContext, pCallback );
+ rInit.maCallbacks.erase(std::remove(rInit.maCallbacks.begin(), rInit.maCallbacks.end(), aEntry),
+ rInit.maCallbacks.end());
+ }
+}
+
+static void typelib_typedescription_initTables(
+ typelib_TypeDescription * pTD )
+{
+ typelib_InterfaceTypeDescription * pITD = reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD);
+
+ std::vector<bool> aReadWriteAttributes(pITD->nAllMembers);
+ for ( sal_Int32 i = pITD->nAllMembers; i--; )
+ {
+ aReadWriteAttributes[i] = false;
+ if( typelib_TypeClass_INTERFACE_ATTRIBUTE == pITD->ppAllMembers[i]->eTypeClass )
+ {
+ typelib_TypeDescription * pM = nullptr;
+ TYPELIB_DANGER_GET( &pM, pITD->ppAllMembers[i] );
+ OSL_ASSERT( pM );
+ if (pM)
+ {
+ aReadWriteAttributes[i] = !reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>(pM)->bReadOnly;
+ TYPELIB_DANGER_RELEASE( pM );
+ }
+ else
+ {
+ SAL_INFO( "cppu.typelib", "cannot get attribute type description: " << pITD->ppAllMembers[i]->pTypeName );
+ }
+ }
+ }
+
+ MutexGuard aGuard( Init().maMutex );
+ if( pTD->bComplete )
+ return;
+
+ // create the index table from member to function table
+ pITD->pMapMemberIndexToFunctionIndex = new sal_Int32[ pITD->nAllMembers ];
+ sal_Int32 nAdditionalOffset = 0; // +1 for read/write attributes
+ sal_Int32 i;
+ for( i = 0; i < pITD->nAllMembers; i++ )
+ {
+ // index to the get method of the attribute
+ pITD->pMapMemberIndexToFunctionIndex[i] = i + nAdditionalOffset;
+ // extra offset if it is a read/write attribute?
+ if (aReadWriteAttributes[i])
+ {
+ // a read/write attribute
+ nAdditionalOffset++;
+ }
+ }
+
+ // create the index table from function to member table
+ pITD->pMapFunctionIndexToMemberIndex = new sal_Int32[ pITD->nAllMembers + nAdditionalOffset ];
+ nAdditionalOffset = 0; // +1 for read/write attributes
+ for( i = 0; i < pITD->nAllMembers; i++ )
+ {
+ // index to the get method of the attribute
+ pITD->pMapFunctionIndexToMemberIndex[i + nAdditionalOffset] = i;
+ // extra offset if it is a read/write attribute?
+ if (aReadWriteAttributes[i])
+ {
+ // a read/write attribute
+ pITD->pMapFunctionIndexToMemberIndex[i + ++nAdditionalOffset] = i;
+ }
+ }
+ // must be the last action after all initialization is done
+ pITD->nMapFunctionIndexToMemberIndex = pITD->nAllMembers + nAdditionalOffset;
+ pTD->bComplete = true;
+}
+
+namespace {
+
+template<typename T> T * allocTypeDescription() {
+ return reinterpret_cast<T *>(new char[sizeof (T)]);
+}
+
+void freeTypeDescription(typelib_TypeDescription const * desc) {
+ delete[] reinterpret_cast<char const *>(desc);
+}
+
+// In some situations (notably typelib_typedescription_newInterfaceMethod and
+// typelib_typedescription_newInterfaceAttribute), only the members nMembers,
+// ppMembers, nAllMembers, and ppAllMembers of an incomplete interface type
+// description are necessary, but not the additional
+// pMapMemberIndexToFunctionIndex, nMapFunctionIndexToMemberIndex, and
+// pMapFunctionIndexToMemberIndex (which are computed by
+// typelib_typedescription_initTables). Furthermore, in those situations, it
+// might be illegal to compute those tables, as the creation of the interface
+// member type descriptions would recursively require a complete interface type
+// description. The parameter initTables controls whether or not to call
+// typelib_typedescription_initTables in those situations.
+bool complete(typelib_TypeDescription ** ppTypeDescr, bool initTables) {
+ if ((*ppTypeDescr)->bComplete)
+ return true;
+
+ OSL_ASSERT( (typelib_TypeClass_STRUCT == (*ppTypeDescr)->eTypeClass ||
+ typelib_TypeClass_EXCEPTION == (*ppTypeDescr)->eTypeClass ||
+ typelib_TypeClass_ENUM == (*ppTypeDescr)->eTypeClass ||
+ typelib_TypeClass_INTERFACE == (*ppTypeDescr)->eTypeClass) &&
+ !TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( (*ppTypeDescr)->eTypeClass ) );
+
+ if (typelib_TypeClass_INTERFACE == (*ppTypeDescr)->eTypeClass &&
+ reinterpret_cast<typelib_InterfaceTypeDescription *>(*ppTypeDescr)->ppAllMembers)
+ {
+ if (initTables) {
+ typelib_typedescription_initTables( *ppTypeDescr );
+ }
+ return true;
+ }
+
+ typelib_TypeDescription * pTD = nullptr;
+ // on demand access of complete td
+ TypeDescriptor_Init_Impl &rInit = Init();
+ rInit.callChain( &pTD, (*ppTypeDescr)->pTypeName );
+ if (pTD)
+ {
+ if (typelib_TypeClass_TYPEDEF == pTD->eTypeClass)
+ {
+ typelib_typedescriptionreference_getDescription(
+ &pTD, reinterpret_cast<typelib_IndirectTypeDescription *>(pTD)->pType );
+ OSL_ASSERT( pTD );
+ if (! pTD)
+ return false;
+ }
+
+ OSL_ASSERT( typelib_TypeClass_TYPEDEF != pTD->eTypeClass );
+ // typedescription found
+ // set to on demand
+ pTD->bOnDemand = true;
+
+ if (pTD->eTypeClass == typelib_TypeClass_INTERFACE
+ && !pTD->bComplete && initTables)
+ {
+ // mandatory info from callback chain
+ OSL_ASSERT( reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD)->ppAllMembers );
+ // complete except of tables init
+ typelib_typedescription_initTables( pTD );
+ pTD->bComplete = true;
+ }
+
+ // The type description is hold by the reference until
+ // on demand is activated.
+ ::typelib_typedescription_register( &pTD ); // replaces incomplete one
+ OSL_ASSERT( pTD == *ppTypeDescr ); // has to merge into existing one
+
+ // insert into the cache
+ MutexGuard aGuard( rInit.maMutex );
+ if( rInit.maCache.size() >= nCacheSize )
+ {
+ typelib_typedescription_release( rInit.maCache.front() );
+ rInit.maCache.pop_front();
+ }
+ // descriptions in the cache must be acquired!
+ typelib_typedescription_acquire( pTD );
+ rInit.maCache.push_back( pTD );
+
+ OSL_ASSERT(
+ pTD->bComplete
+ || (pTD->eTypeClass == typelib_TypeClass_INTERFACE
+ && !initTables));
+
+ ::typelib_typedescription_release( *ppTypeDescr );
+ *ppTypeDescr = pTD;
+ }
+ else
+ {
+ SAL_INFO(
+ "cppu.typelib",
+ "type cannot be completed: " << OUString::unacquired(&(*ppTypeDescr)->pTypeName));
+ return false;
+ }
+ return true;
+}
+
+}
+
+
+extern "C" void typelib_typedescription_newEmpty(
+ typelib_TypeDescription ** ppRet,
+ typelib_TypeClass eTypeClass, rtl_uString * pTypeName )
+ SAL_THROW_EXTERN_C()
+{
+ if( *ppRet )
+ {
+ typelib_typedescription_release( *ppRet );
+ *ppRet = nullptr;
+ }
+
+ OSL_ASSERT( typelib_TypeClass_TYPEDEF != eTypeClass );
+
+ typelib_TypeDescription * pRet;
+ switch( eTypeClass )
+ {
+ case typelib_TypeClass_SEQUENCE:
+ {
+ auto pTmp = allocTypeDescription<typelib_IndirectTypeDescription>();
+ pRet = &pTmp->aBase;
+#if OSL_DEBUG_LEVEL > 0
+ osl_atomic_increment( &Init().nIndirectTypeDescriptionCount );
+#endif
+ pTmp->pType = nullptr;
+ // coverity[leaked_storage] - this is on purpose
+ }
+ break;
+
+ case typelib_TypeClass_STRUCT:
+ {
+ // FEATURE_EMPTYCLASS
+ auto pTmp = allocTypeDescription<typelib_StructTypeDescription>();
+ pRet = &pTmp->aBase.aBase;
+#if OSL_DEBUG_LEVEL > 0
+ osl_atomic_increment( &Init().nCompoundTypeDescriptionCount );
+#endif
+ pTmp->aBase.pBaseTypeDescription = nullptr;
+ pTmp->aBase.nMembers = 0;
+ pTmp->aBase.pMemberOffsets = nullptr;
+ pTmp->aBase.ppTypeRefs = nullptr;
+ pTmp->aBase.ppMemberNames = nullptr;
+ pTmp->pParameterizedTypes = nullptr;
+ // coverity[leaked_storage] - this is on purpose
+ }
+ break;
+
+ case typelib_TypeClass_EXCEPTION:
+ {
+ // FEATURE_EMPTYCLASS
+ auto pTmp = allocTypeDescription<typelib_CompoundTypeDescription>();
+ pRet = &pTmp->aBase;
+#if OSL_DEBUG_LEVEL > 0
+ osl_atomic_increment( &Init().nCompoundTypeDescriptionCount );
+#endif
+ pTmp->pBaseTypeDescription = nullptr;
+ pTmp->nMembers = 0;
+ pTmp->pMemberOffsets = nullptr;
+ pTmp->ppTypeRefs = nullptr;
+ pTmp->ppMemberNames = nullptr;
+ // coverity[leaked_storage] - this is on purpose
+ }
+ break;
+
+ case typelib_TypeClass_ENUM:
+ {
+ auto pTmp = allocTypeDescription<typelib_EnumTypeDescription>();
+ pRet = &pTmp->aBase;
+#if OSL_DEBUG_LEVEL > 0
+ osl_atomic_increment( &Init().nEnumTypeDescriptionCount );
+#endif
+ pTmp->nDefaultEnumValue = 0;
+ pTmp->nEnumValues = 0;
+ pTmp->ppEnumNames = nullptr;
+ pTmp->pEnumValues = nullptr;
+ // coverity[leaked_storage] - this is on purpose
+ }
+ break;
+
+ case typelib_TypeClass_INTERFACE:
+ {
+ auto pTmp = allocTypeDescription<
+ typelib_InterfaceTypeDescription>();
+ pRet = &pTmp->aBase;
+#if OSL_DEBUG_LEVEL > 0
+ osl_atomic_increment( &Init().nInterfaceTypeDescriptionCount );
+#endif
+ pTmp->pBaseTypeDescription = nullptr;
+ pTmp->nMembers = 0;
+ pTmp->ppMembers = nullptr;
+ pTmp->nAllMembers = 0;
+ pTmp->ppAllMembers = nullptr;
+ pTmp->nMapFunctionIndexToMemberIndex = 0;
+ pTmp->pMapFunctionIndexToMemberIndex = nullptr;
+ pTmp->pMapMemberIndexToFunctionIndex= nullptr;
+ pTmp->nBaseTypes = 0;
+ pTmp->ppBaseTypes = nullptr;
+ // coverity[leaked_storage] - this is on purpose
+ }
+ break;
+
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ auto pTmp = allocTypeDescription<
+ typelib_InterfaceMethodTypeDescription>();
+ pRet = &pTmp->aBase.aBase;
+#if OSL_DEBUG_LEVEL > 0
+ osl_atomic_increment( &Init().nInterfaceMethodTypeDescriptionCount );
+#endif
+ pTmp->aBase.pMemberName = nullptr;
+ pTmp->pReturnTypeRef = nullptr;
+ pTmp->nParams = 0;
+ pTmp->pParams = nullptr;
+ pTmp->nExceptions = 0;
+ pTmp->ppExceptions = nullptr;
+ pTmp->pInterface = nullptr;
+ pTmp->pBaseRef = nullptr;
+ pTmp->nIndex = 0;
+ // coverity[leaked_storage] - this is on purpose
+ }
+ break;
+
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ {
+ auto * pTmp = allocTypeDescription<
+ typelib_InterfaceAttributeTypeDescription>();
+ pRet = &pTmp->aBase.aBase;
+#if OSL_DEBUG_LEVEL > 0
+ osl_atomic_increment( &Init().nInterfaceAttributeTypeDescriptionCount );
+#endif
+ pTmp->aBase.pMemberName = nullptr;
+ pTmp->pAttributeTypeRef = nullptr;
+ pTmp->pInterface = nullptr;
+ pTmp->pBaseRef = nullptr;
+ pTmp->nIndex = 0;
+ pTmp->nGetExceptions = 0;
+ pTmp->ppGetExceptions = nullptr;
+ pTmp->nSetExceptions = 0;
+ pTmp->ppSetExceptions = nullptr;
+ // coverity[leaked_storage] - this is on purpose
+ }
+ break;
+
+ default:
+ {
+ pRet = allocTypeDescription<typelib_TypeDescription>();
+#if OSL_DEBUG_LEVEL > 0
+ osl_atomic_increment( &Init().nTypeDescriptionCount );
+#endif
+ }
+ }
+
+ pRet->nRefCount = 1; // reference count is initially 1
+ pRet->nStaticRefCount = 0;
+ pRet->eTypeClass = eTypeClass;
+ pRet->pUniqueIdentifier = nullptr;
+ pRet->pReserved = nullptr;
+ pRet->pTypeName = pTypeName;
+ rtl_uString_acquire( pRet->pTypeName );
+ pRet->pSelf = pRet;
+ pRet->bComplete = true;
+ pRet->nSize = 0;
+ pRet->nAlignment = 0;
+ pRet->pWeakRef = nullptr;
+ pRet->bOnDemand = false;
+ *ppRet = pRet;
+}
+
+
+namespace {
+
+void newTypeDescription(
+ typelib_TypeDescription ** ppRet, typelib_TypeClass eTypeClass,
+ rtl_uString * pTypeName, typelib_TypeDescriptionReference * pType,
+ sal_Int32 nMembers, typelib_CompoundMember_Init * pCompoundMembers,
+ typelib_StructMember_Init * pStructMembers)
+{
+ OSL_ASSERT(
+ (pCompoundMembers == nullptr || pStructMembers == nullptr)
+ && (pStructMembers == nullptr || eTypeClass == typelib_TypeClass_STRUCT));
+ if (typelib_TypeClass_TYPEDEF == eTypeClass)
+ {
+ SAL_WARN("cppu.typelib", "unexpected typedef!" );
+ typelib_typedescriptionreference_getDescription( ppRet, pType );
+ return;
+ }
+
+ typelib_typedescription_newEmpty( ppRet, eTypeClass, pTypeName );
+
+ switch( eTypeClass )
+ {
+ case typelib_TypeClass_SEQUENCE:
+ {
+ OSL_ASSERT( nMembers == 0 );
+ typelib_typedescriptionreference_acquire( pType );
+ reinterpret_cast<typelib_IndirectTypeDescription *>(*ppRet)->pType = pType;
+ }
+ break;
+
+ case typelib_TypeClass_EXCEPTION:
+ case typelib_TypeClass_STRUCT:
+ {
+ // FEATURE_EMPTYCLASS
+ typelib_CompoundTypeDescription * pTmp = reinterpret_cast<typelib_CompoundTypeDescription*>(*ppRet);
+
+ sal_Int32 nOffset = 0;
+ if( pType )
+ {
+ typelib_typedescriptionreference_getDescription(
+ reinterpret_cast<typelib_TypeDescription **>(&pTmp->pBaseTypeDescription), pType );
+ nOffset = pTmp->pBaseTypeDescription->aBase.nSize;
+ OSL_ENSURE( newAlignedSize( 0, pTmp->pBaseTypeDescription->aBase.nSize, pTmp->pBaseTypeDescription->aBase.nAlignment ) == pTmp->pBaseTypeDescription->aBase.nSize, "### unexpected offset!" );
+ }
+ if( nMembers )
+ {
+ pTmp->nMembers = nMembers;
+ pTmp->pMemberOffsets = new sal_Int32[ nMembers ];
+ pTmp->ppTypeRefs = new typelib_TypeDescriptionReference *[ nMembers ];
+ pTmp->ppMemberNames = new rtl_uString *[ nMembers ];
+ bool polymorphic = eTypeClass == typelib_TypeClass_STRUCT
+ && OUString::unacquired(&pTypeName).indexOf('<') >= 0;
+ OSL_ASSERT(!polymorphic || pStructMembers != nullptr);
+ if (polymorphic) {
+ reinterpret_cast< typelib_StructTypeDescription * >(pTmp)->
+ pParameterizedTypes = new sal_Bool[nMembers];
+ }
+ for( sal_Int32 i = 0 ; i < nMembers; i++ )
+ {
+ // read the type and member names
+ pTmp->ppTypeRefs[i] = nullptr;
+ if (pCompoundMembers != nullptr) {
+ typelib_typedescriptionreference_new(
+ pTmp->ppTypeRefs +i, pCompoundMembers[i].eTypeClass,
+ pCompoundMembers[i].pTypeName );
+ pTmp->ppMemberNames[i]
+ = pCompoundMembers[i].pMemberName;
+ rtl_uString_acquire( pTmp->ppMemberNames[i] );
+ } else {
+ typelib_typedescriptionreference_new(
+ pTmp->ppTypeRefs +i,
+ pStructMembers[i].aBase.eTypeClass,
+ pStructMembers[i].aBase.pTypeName );
+ pTmp->ppMemberNames[i]
+ = pStructMembers[i].aBase.pMemberName;
+ rtl_uString_acquire(pTmp->ppMemberNames[i]);
+ }
+ // write offset
+ sal_Int32 size;
+ sal_Int32 alignment;
+ if (pTmp->ppTypeRefs[i]->eTypeClass ==
+ typelib_TypeClass_SEQUENCE)
+ {
+ // Take care of recursion like
+ // struct S { sequence<S> x; };
+ size = sizeof(void *);
+ alignment = adjustAlignment(size);
+ } else {
+ typelib_TypeDescription * pTD = nullptr;
+ TYPELIB_DANGER_GET( &pTD, pTmp->ppTypeRefs[i] );
+ OSL_ENSURE( pTD->nSize, "### void member?" );
+ size = pTD->nSize;
+ alignment = pTD->nAlignment;
+ TYPELIB_DANGER_RELEASE( pTD );
+ }
+ nOffset = newAlignedSize( nOffset, size, alignment );
+ pTmp->pMemberOffsets[i] = nOffset - size;
+
+ if (polymorphic) {
+ reinterpret_cast< typelib_StructTypeDescription * >(
+ pTmp)->pParameterizedTypes[i]
+ = pStructMembers[i].bParameterizedType;
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if( !TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( eTypeClass ) )
+ (*ppRet)->pWeakRef = reinterpret_cast<typelib_TypeDescriptionReference *>(*ppRet);
+ if( eTypeClass != typelib_TypeClass_VOID )
+ {
+ // sizeof(void) not allowed
+ (*ppRet)->nSize = typelib_typedescription_getAlignedUnoSize( (*ppRet), 0, (*ppRet)->nAlignment );
+ (*ppRet)->nAlignment = adjustAlignment( (*ppRet)->nAlignment );
+ }
+}
+
+}
+
+extern "C" void SAL_CALL typelib_typedescription_new(
+ typelib_TypeDescription ** ppRet,
+ typelib_TypeClass eTypeClass,
+ rtl_uString * pTypeName,
+ typelib_TypeDescriptionReference * pType,
+ sal_Int32 nMembers,
+ typelib_CompoundMember_Init * pMembers )
+ SAL_THROW_EXTERN_C()
+{
+ newTypeDescription(
+ ppRet, eTypeClass, pTypeName, pType, nMembers, pMembers, nullptr);
+}
+
+extern "C" void SAL_CALL typelib_typedescription_newStruct(
+ typelib_TypeDescription ** ppRet,
+ rtl_uString * pTypeName,
+ typelib_TypeDescriptionReference * pType,
+ sal_Int32 nMembers,
+ typelib_StructMember_Init * pMembers )
+ SAL_THROW_EXTERN_C()
+{
+ newTypeDescription(
+ ppRet, typelib_TypeClass_STRUCT, pTypeName, pType, nMembers, nullptr,
+ pMembers);
+}
+
+
+extern "C" void SAL_CALL typelib_typedescription_newEnum(
+ typelib_TypeDescription ** ppRet,
+ rtl_uString * pTypeName,
+ sal_Int32 nDefaultValue,
+ sal_Int32 nEnumValues,
+ rtl_uString ** ppEnumNames,
+ sal_Int32 * pEnumValues )
+ SAL_THROW_EXTERN_C()
+{
+ typelib_typedescription_newEmpty( ppRet, typelib_TypeClass_ENUM, pTypeName );
+ typelib_EnumTypeDescription * pEnum = reinterpret_cast<typelib_EnumTypeDescription *>(*ppRet);
+
+ pEnum->nDefaultEnumValue = nDefaultValue;
+ pEnum->nEnumValues = nEnumValues;
+ pEnum->ppEnumNames = new rtl_uString * [ nEnumValues ];
+ for ( sal_Int32 nPos = nEnumValues; nPos--; )
+ {
+ pEnum->ppEnumNames[nPos] = ppEnumNames[nPos];
+ rtl_uString_acquire( pEnum->ppEnumNames[nPos] );
+ }
+ pEnum->pEnumValues = new sal_Int32[ nEnumValues ];
+ ::memcpy( pEnum->pEnumValues, pEnumValues, nEnumValues * sizeof(sal_Int32) );
+
+ static_assert(!TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK(typelib_TypeClass_ENUM));
+ (*ppRet)->pWeakRef = reinterpret_cast<typelib_TypeDescriptionReference *>(*ppRet);
+ // sizeof(void) not allowed
+ (*ppRet)->nSize = typelib_typedescription_getAlignedUnoSize( (*ppRet), 0, (*ppRet)->nAlignment );
+ (*ppRet)->nAlignment = adjustAlignment( (*ppRet)->nAlignment );
+}
+
+
+extern "C" void SAL_CALL typelib_typedescription_newInterface(
+ typelib_InterfaceTypeDescription ** ppRet,
+ rtl_uString * pTypeName,
+ SAL_UNUSED_PARAMETER sal_uInt32, SAL_UNUSED_PARAMETER sal_uInt16,
+ SAL_UNUSED_PARAMETER sal_uInt16, SAL_UNUSED_PARAMETER sal_uInt32,
+ SAL_UNUSED_PARAMETER sal_uInt32,
+ typelib_TypeDescriptionReference * pBaseInterface,
+ sal_Int32 nMembers,
+ typelib_TypeDescriptionReference ** ppMembers )
+ SAL_THROW_EXTERN_C()
+{
+ // coverity[callee_ptr_arith] - not a bug
+ typelib_typedescription_newMIInterface(
+ ppRet, pTypeName, 0, 0, 0, 0, 0, pBaseInterface == nullptr ? 0 : 1,
+ &pBaseInterface, nMembers, ppMembers);
+}
+
+namespace {
+
+class BaseList {
+public:
+ struct Entry {
+ sal_Int32 memberOffset;
+ sal_Int32 directBaseIndex;
+ sal_Int32 directBaseMemberOffset;
+ typelib_InterfaceTypeDescription const * base;
+ };
+
+ typedef std::vector< Entry > List;
+
+ explicit BaseList(typelib_InterfaceTypeDescription const * desc);
+
+ List const & getList() const { return list; }
+
+ sal_Int32 getBaseMembers() const { return members; }
+
+private:
+ typedef std::set< OUString > Set;
+
+ void calculate(
+ Set& allSet,
+ sal_Int32 directBaseIndex, Set & directBaseSet,
+ sal_Int32 * directBaseMembers,
+ typelib_InterfaceTypeDescription const * desc);
+
+ List list;
+ sal_Int32 members;
+};
+
+BaseList::BaseList(typelib_InterfaceTypeDescription const * desc)
+ : members(0)
+{
+ Set allSet;
+ for (sal_Int32 i = 0; i < desc->nBaseTypes; ++i) {
+ Set directBaseSet;
+ sal_Int32 directBaseMembers = 0;
+ calculate(allSet, i, directBaseSet, &directBaseMembers, desc->ppBaseTypes[i]);
+ }
+}
+
+void BaseList::calculate(
+ Set& allSet,
+ sal_Int32 directBaseIndex, Set & directBaseSet,
+ sal_Int32 * directBaseMembers,
+ typelib_InterfaceTypeDescription const * desc)
+{
+ for (sal_Int32 i = 0; i < desc->nBaseTypes; ++i) {
+ calculate(allSet,
+ directBaseIndex, directBaseSet, directBaseMembers,
+ desc->ppBaseTypes[i]);
+ }
+ if (allSet.insert(desc->aBase.pTypeName).second) {
+ Entry e;
+ e.memberOffset = members;
+ e.directBaseIndex = directBaseIndex;
+ e.directBaseMemberOffset = *directBaseMembers;
+ e.base = desc;
+ list.push_back(e);
+ OSL_ASSERT(desc->ppAllMembers != nullptr);
+ members += desc->nMembers;
+ }
+ if (directBaseSet.insert(desc->aBase.pTypeName).second) {
+ OSL_ASSERT(desc->ppAllMembers != nullptr);
+ *directBaseMembers += desc->nMembers;
+ }
+}
+
+}
+
+extern "C" void SAL_CALL typelib_typedescription_newMIInterface(
+ typelib_InterfaceTypeDescription ** ppRet,
+ rtl_uString * pTypeName,
+ SAL_UNUSED_PARAMETER sal_uInt32, SAL_UNUSED_PARAMETER sal_uInt16,
+ SAL_UNUSED_PARAMETER sal_uInt16, SAL_UNUSED_PARAMETER sal_uInt32,
+ SAL_UNUSED_PARAMETER sal_uInt32,
+ sal_Int32 nBaseInterfaces,
+ typelib_TypeDescriptionReference ** ppBaseInterfaces,
+ sal_Int32 nMembers,
+ typelib_TypeDescriptionReference ** ppMembers )
+ SAL_THROW_EXTERN_C()
+{
+ if (*ppRet != nullptr) {
+ typelib_typedescription_release(&(*ppRet)->aBase);
+ *ppRet = nullptr;
+ }
+
+ typelib_InterfaceTypeDescription * pITD = nullptr;
+ typelib_typedescription_newEmpty(
+ reinterpret_cast<typelib_TypeDescription **>(&pITD), typelib_TypeClass_INTERFACE, pTypeName );
+
+ pITD->nBaseTypes = nBaseInterfaces;
+ pITD->ppBaseTypes = new typelib_InterfaceTypeDescription *[nBaseInterfaces];
+ for (sal_Int32 i = 0; i < nBaseInterfaces; ++i) {
+ pITD->ppBaseTypes[i] = nullptr;
+ typelib_typedescriptionreference_getDescription(
+ reinterpret_cast< typelib_TypeDescription ** >(
+ &pITD->ppBaseTypes[i]),
+ ppBaseInterfaces[i]);
+ if (pITD->ppBaseTypes[i] == nullptr
+ || !complete(
+ reinterpret_cast< typelib_TypeDescription ** >(
+ &pITD->ppBaseTypes[i]),
+ false))
+ {
+ OSL_ASSERT(false);
+ return;
+ }
+ OSL_ASSERT(pITD->ppBaseTypes[i] != nullptr);
+ }
+ if (nBaseInterfaces > 0) {
+ pITD->pBaseTypeDescription = pITD->ppBaseTypes[0];
+ }
+ // set the
+ pITD->aUik.m_Data1 = 0;
+ pITD->aUik.m_Data2 = 0;
+ pITD->aUik.m_Data3 = 0;
+ pITD->aUik.m_Data4 = 0;
+ pITD->aUik.m_Data5 = 0;
+
+ BaseList aBaseList(pITD);
+ pITD->nAllMembers = nMembers + aBaseList.getBaseMembers();
+ pITD->nMembers = nMembers;
+
+ if( pITD->nAllMembers )
+ {
+ // at minimum one member exist, allocate the memory
+ pITD->ppAllMembers = new typelib_TypeDescriptionReference *[ pITD->nAllMembers ];
+ sal_Int32 n = 0;
+
+ BaseList::List const & rList = aBaseList.getList();
+ for (const auto& rEntry : rList)
+ {
+ typelib_InterfaceTypeDescription const * pBase = rEntry.base;
+ typelib_InterfaceTypeDescription const * pDirectBase
+ = pITD->ppBaseTypes[rEntry.directBaseIndex];
+ OSL_ASSERT(pBase->ppAllMembers != nullptr);
+ for (sal_Int32 j = 0; j < pBase->nMembers; ++j) {
+ typelib_TypeDescriptionReference const * pDirectBaseMember
+ = pDirectBase->ppAllMembers[rEntry.directBaseMemberOffset + j];
+ OUString aName = OUString::unacquired(&pDirectBaseMember->pTypeName) +
+ ":@" +
+ OUString::number(rEntry.directBaseIndex) +
+ "," +
+ OUString::number(rEntry.memberOffset + j) +
+ ":" +
+ OUString::unacquired(&pITD->aBase.pTypeName);
+ typelib_TypeDescriptionReference * pDerivedMember = nullptr;
+ typelib_typedescriptionreference_new(
+ &pDerivedMember, pDirectBaseMember->eTypeClass,
+ aName.pData);
+ pITD->ppAllMembers[n++] = pDerivedMember;
+ }
+ }
+
+ if( nMembers )
+ {
+ pITD->ppMembers = pITD->ppAllMembers + aBaseList.getBaseMembers();
+ }
+
+ // add own members
+ for( sal_Int32 i = 0; i < nMembers; i++ )
+ {
+ typelib_typedescriptionreference_acquire( ppMembers[i] );
+ pITD->ppAllMembers[n++] = ppMembers[i];
+ }
+ }
+
+ typelib_TypeDescription * pTmp = &pITD->aBase;
+ static_assert( !TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( typelib_TypeClass_INTERFACE ) );
+ pTmp->pWeakRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pTmp);
+ pTmp->nSize = typelib_typedescription_getAlignedUnoSize( pTmp, 0, pTmp->nAlignment );
+ pTmp->nAlignment = adjustAlignment( pTmp->nAlignment );
+ pTmp->bComplete = false;
+
+ *ppRet = pITD;
+}
+
+
+namespace {
+
+typelib_TypeDescriptionReference ** copyExceptions(
+ sal_Int32 count, rtl_uString ** typeNames)
+{
+ OSL_ASSERT(count >= 0);
+ if (count == 0) {
+ return nullptr;
+ }
+ typelib_TypeDescriptionReference ** p
+ = new typelib_TypeDescriptionReference *[count];
+ for (sal_Int32 i = 0; i < count; ++i) {
+ p[i] = nullptr;
+ typelib_typedescriptionreference_new(
+ p + i, typelib_TypeClass_EXCEPTION, typeNames[i]);
+ }
+ return p;
+}
+
+}
+
+extern "C" void SAL_CALL typelib_typedescription_newInterfaceMethod(
+ typelib_InterfaceMethodTypeDescription ** ppRet,
+ sal_Int32 nAbsolutePosition,
+ sal_Bool bOneWay,
+ rtl_uString * pTypeName,
+ typelib_TypeClass eReturnTypeClass,
+ rtl_uString * pReturnTypeName,
+ sal_Int32 nParams,
+ typelib_Parameter_Init * pParams,
+ sal_Int32 nExceptions,
+ rtl_uString ** ppExceptionNames )
+ SAL_THROW_EXTERN_C()
+{
+ if (*ppRet != nullptr) {
+ typelib_typedescription_release(&(*ppRet)->aBase.aBase);
+ *ppRet = nullptr;
+ }
+ sal_Int32 nOffset = rtl_ustr_lastIndexOfChar_WithLength(
+ pTypeName->buffer, pTypeName->length, ':');
+ if (nOffset <= 0 || pTypeName->buffer[nOffset - 1] != ':') {
+ OSL_FAIL("Bad interface method type name");
+ return;
+ }
+ OUString aInterfaceTypeName(pTypeName->buffer, nOffset - 1);
+ typelib_InterfaceTypeDescription * pInterface = nullptr;
+ typelib_typedescription_getByName(
+ reinterpret_cast< typelib_TypeDescription ** >(&pInterface),
+ aInterfaceTypeName.pData);
+ if (pInterface == nullptr
+ || pInterface->aBase.eTypeClass != typelib_TypeClass_INTERFACE
+ || !complete(
+ reinterpret_cast< typelib_TypeDescription ** >(&pInterface), false))
+ {
+ OSL_FAIL("No interface corresponding to interface method");
+ return;
+ }
+
+ typelib_typedescription_newEmpty(
+ reinterpret_cast<typelib_TypeDescription **>(ppRet), typelib_TypeClass_INTERFACE_METHOD, pTypeName );
+
+ rtl_uString_newFromStr_WithLength( &(*ppRet)->aBase.pMemberName,
+ pTypeName->buffer + nOffset +1,
+ pTypeName->length - nOffset -1 );
+ (*ppRet)->aBase.nPosition = nAbsolutePosition;
+ (*ppRet)->bOneWay = bOneWay;
+ typelib_typedescriptionreference_new( &(*ppRet)->pReturnTypeRef, eReturnTypeClass, pReturnTypeName );
+ (*ppRet)->nParams = nParams;
+ if( nParams )
+ {
+ (*ppRet)->pParams = new typelib_MethodParameter[ nParams ];
+
+ for( sal_Int32 i = 0; i < nParams; i++ )
+ {
+ // get the name of the parameter
+ (*ppRet)->pParams[ i ].pName = pParams[i].pParamName;
+ rtl_uString_acquire( (*ppRet)->pParams[ i ].pName );
+ (*ppRet)->pParams[ i ].pTypeRef = nullptr;
+ // get the type name of the parameter and create the weak reference
+ typelib_typedescriptionreference_new(
+ &(*ppRet)->pParams[ i ].pTypeRef, pParams[i].eTypeClass, pParams[i].pTypeName );
+ (*ppRet)->pParams[ i ].bIn = pParams[i].bIn;
+ (*ppRet)->pParams[ i ].bOut = pParams[i].bOut;
+ }
+ }
+ (*ppRet)->nExceptions = nExceptions;
+ (*ppRet)->ppExceptions = copyExceptions(nExceptions, ppExceptionNames);
+ (*ppRet)->pInterface = pInterface;
+ (*ppRet)->pBaseRef = nullptr;
+ OSL_ASSERT(
+ (nAbsolutePosition >= pInterface->nAllMembers - pInterface->nMembers)
+ && nAbsolutePosition < pInterface->nAllMembers);
+ (*ppRet)->nIndex = nAbsolutePosition
+ - (pInterface->nAllMembers - pInterface->nMembers);
+ static_assert( TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( typelib_TypeClass_INTERFACE_METHOD ) );
+ assert(reinterpret_cast<typelib_TypeDescription *>(*ppRet)->pWeakRef == nullptr);
+}
+
+
+extern "C" void SAL_CALL typelib_typedescription_newInterfaceAttribute(
+ typelib_InterfaceAttributeTypeDescription ** ppRet,
+ sal_Int32 nAbsolutePosition,
+ rtl_uString * pTypeName,
+ typelib_TypeClass eAttributeTypeClass,
+ rtl_uString * pAttributeTypeName,
+ sal_Bool bReadOnly )
+ SAL_THROW_EXTERN_C()
+{
+ typelib_typedescription_newExtendedInterfaceAttribute(
+ ppRet, nAbsolutePosition, pTypeName, eAttributeTypeClass,
+ pAttributeTypeName, bReadOnly, 0, nullptr, 0, nullptr);
+}
+
+
+extern "C" void SAL_CALL typelib_typedescription_newExtendedInterfaceAttribute(
+ typelib_InterfaceAttributeTypeDescription ** ppRet,
+ sal_Int32 nAbsolutePosition,
+ rtl_uString * pTypeName,
+ typelib_TypeClass eAttributeTypeClass,
+ rtl_uString * pAttributeTypeName,
+ sal_Bool bReadOnly,
+ sal_Int32 nGetExceptions, rtl_uString ** ppGetExceptionNames,
+ sal_Int32 nSetExceptions, rtl_uString ** ppSetExceptionNames )
+ SAL_THROW_EXTERN_C()
+{
+ if (*ppRet != nullptr) {
+ typelib_typedescription_release(&(*ppRet)->aBase.aBase);
+ *ppRet = nullptr;
+ }
+ sal_Int32 nOffset = rtl_ustr_lastIndexOfChar_WithLength(
+ pTypeName->buffer, pTypeName->length, ':');
+ if (nOffset <= 0 || pTypeName->buffer[nOffset - 1] != ':') {
+ OSL_FAIL("Bad interface attribute type name");
+ return;
+ }
+ OUString aInterfaceTypeName(pTypeName->buffer, nOffset - 1);
+ typelib_InterfaceTypeDescription * pInterface = nullptr;
+ typelib_typedescription_getByName(
+ reinterpret_cast< typelib_TypeDescription ** >(&pInterface),
+ aInterfaceTypeName.pData);
+ if (pInterface == nullptr
+ || pInterface->aBase.eTypeClass != typelib_TypeClass_INTERFACE
+ || !complete(
+ reinterpret_cast< typelib_TypeDescription ** >(&pInterface), false))
+ {
+ OSL_FAIL("No interface corresponding to interface attribute");
+ return;
+ }
+
+ typelib_typedescription_newEmpty(
+ reinterpret_cast<typelib_TypeDescription **>(ppRet), typelib_TypeClass_INTERFACE_ATTRIBUTE, pTypeName );
+
+ rtl_uString_newFromStr_WithLength( &(*ppRet)->aBase.pMemberName,
+ pTypeName->buffer + nOffset +1,
+ pTypeName->length - nOffset -1 );
+ (*ppRet)->aBase.nPosition = nAbsolutePosition;
+ typelib_typedescriptionreference_new( &(*ppRet)->pAttributeTypeRef, eAttributeTypeClass, pAttributeTypeName );
+ (*ppRet)->bReadOnly = bReadOnly;
+ (*ppRet)->pInterface = pInterface;
+ (*ppRet)->pBaseRef = nullptr;
+ OSL_ASSERT(
+ (nAbsolutePosition >= pInterface->nAllMembers - pInterface->nMembers)
+ && nAbsolutePosition < pInterface->nAllMembers);
+ (*ppRet)->nIndex = nAbsolutePosition
+ - (pInterface->nAllMembers - pInterface->nMembers);
+ (*ppRet)->nGetExceptions = nGetExceptions;
+ (*ppRet)->ppGetExceptions = copyExceptions(
+ nGetExceptions, ppGetExceptionNames);
+ (*ppRet)->nSetExceptions = nSetExceptions;
+ (*ppRet)->ppSetExceptions = copyExceptions(
+ nSetExceptions, ppSetExceptionNames);
+ static_assert( TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( typelib_TypeClass_INTERFACE_ATTRIBUTE ) );
+ assert(reinterpret_cast<typelib_TypeDescription *>(*ppRet)->pWeakRef == nullptr);
+}
+
+
+extern "C" void SAL_CALL typelib_typedescription_acquire(
+ typelib_TypeDescription * pTypeDescription )
+ SAL_THROW_EXTERN_C()
+{
+ osl_atomic_increment( &pTypeDescription->nRefCount );
+}
+
+
+namespace {
+
+void deleteExceptions(
+ sal_Int32 count, typelib_TypeDescriptionReference ** exceptions)
+{
+ for (sal_Int32 i = 0; i < count; ++i) {
+ typelib_typedescriptionreference_release(exceptions[i]);
+ }
+ delete[] exceptions;
+}
+
+}
+
+// frees anything except typelib_TypeDescription base!
+static void typelib_typedescription_destructExtendedMembers(
+ typelib_TypeDescription * pTD )
+{
+ OSL_ASSERT( typelib_TypeClass_TYPEDEF != pTD->eTypeClass );
+
+ switch( pTD->eTypeClass )
+ {
+ case typelib_TypeClass_SEQUENCE:
+ if( reinterpret_cast<typelib_IndirectTypeDescription*>(pTD)->pType )
+ typelib_typedescriptionreference_release( reinterpret_cast<typelib_IndirectTypeDescription*>(pTD)->pType );
+ break;
+ case typelib_TypeClass_STRUCT:
+ delete[] reinterpret_cast< typelib_StructTypeDescription * >(pTD)->
+ pParameterizedTypes;
+ [[fallthrough]];
+ case typelib_TypeClass_EXCEPTION:
+ {
+ typelib_CompoundTypeDescription * pCTD = reinterpret_cast<typelib_CompoundTypeDescription*>(pTD);
+ if( pCTD->pBaseTypeDescription )
+ typelib_typedescription_release( &pCTD->pBaseTypeDescription->aBase );
+ sal_Int32 i;
+ for( i = 0; i < pCTD->nMembers; i++ )
+ {
+ typelib_typedescriptionreference_release( pCTD->ppTypeRefs[i] );
+ }
+ if (pCTD->ppMemberNames)
+ {
+ for ( i = 0; i < pCTD->nMembers; i++ )
+ {
+ rtl_uString_release( pCTD->ppMemberNames[i] );
+ }
+ delete [] pCTD->ppMemberNames;
+ }
+ delete [] pCTD->ppTypeRefs;
+ delete [] pCTD->pMemberOffsets;
+ }
+ break;
+ case typelib_TypeClass_INTERFACE:
+ {
+ typelib_InterfaceTypeDescription * pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD);
+ for( sal_Int32 i = 0; i < pITD->nAllMembers; i++ )
+ {
+ typelib_typedescriptionreference_release( pITD->ppAllMembers[i] );
+ }
+ delete [] pITD->ppAllMembers;
+ delete [] pITD->pMapMemberIndexToFunctionIndex;
+ delete [] pITD->pMapFunctionIndexToMemberIndex;
+ for (sal_Int32 i = 0; i < pITD->nBaseTypes; ++i) {
+ typelib_typedescription_release(
+ reinterpret_cast< typelib_TypeDescription * >(
+ pITD->ppBaseTypes[i]));
+ }
+ delete[] pITD->ppBaseTypes;
+ break;
+ }
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ typelib_InterfaceMethodTypeDescription * pIMTD = reinterpret_cast<typelib_InterfaceMethodTypeDescription*>(pTD);
+ if( pIMTD->pReturnTypeRef )
+ typelib_typedescriptionreference_release( pIMTD->pReturnTypeRef );
+ for( sal_Int32 i = 0; i < pIMTD->nParams; i++ )
+ {
+ rtl_uString_release( pIMTD->pParams[ i ].pName );
+ typelib_typedescriptionreference_release( pIMTD->pParams[ i ].pTypeRef );
+ }
+ delete [] pIMTD->pParams;
+ deleteExceptions(pIMTD->nExceptions, pIMTD->ppExceptions);
+ rtl_uString_release( pIMTD->aBase.pMemberName );
+ typelib_typedescription_release(&pIMTD->pInterface->aBase);
+ if (pIMTD->pBaseRef != nullptr) {
+ typelib_typedescriptionreference_release(pIMTD->pBaseRef);
+ }
+ }
+ break;
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ {
+ typelib_InterfaceAttributeTypeDescription * pIATD = reinterpret_cast<typelib_InterfaceAttributeTypeDescription*>(pTD);
+ deleteExceptions(pIATD->nGetExceptions, pIATD->ppGetExceptions);
+ deleteExceptions(pIATD->nSetExceptions, pIATD->ppSetExceptions);
+ if( pIATD->pAttributeTypeRef )
+ typelib_typedescriptionreference_release( pIATD->pAttributeTypeRef );
+ if( pIATD->aBase.pMemberName )
+ rtl_uString_release( pIATD->aBase.pMemberName );
+ typelib_typedescription_release(&pIATD->pInterface->aBase);
+ if (pIATD->pBaseRef != nullptr) {
+ typelib_typedescriptionreference_release(pIATD->pBaseRef);
+ }
+ }
+ break;
+ case typelib_TypeClass_ENUM:
+ {
+ typelib_EnumTypeDescription * pEnum = reinterpret_cast<typelib_EnumTypeDescription *>(pTD);
+ for ( sal_Int32 nPos = pEnum->nEnumValues; nPos--; )
+ {
+ rtl_uString_release( pEnum->ppEnumNames[nPos] );
+ }
+ delete [] pEnum->ppEnumNames;
+ delete [] pEnum->pEnumValues;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+
+extern "C" void SAL_CALL typelib_typedescription_release(
+ typelib_TypeDescription * pTD )
+ SAL_THROW_EXTERN_C()
+{
+ sal_Int32 ref = osl_atomic_decrement( &pTD->nRefCount );
+ OSL_ASSERT(ref >= 0);
+ if (0 != ref)
+ return;
+
+ TypeDescriptor_Init_Impl &rInit = Init();
+ if( TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( pTD->eTypeClass ) )
+ {
+ if( pTD->pWeakRef )
+ {
+ {
+ MutexGuard aGuard( rInit.maMutex );
+ // remove this description from the weak reference
+ pTD->pWeakRef->pType = nullptr;
+ }
+ typelib_typedescriptionreference_release( pTD->pWeakRef );
+ }
+ }
+ else
+ {
+ // this description is a reference too, so remove it from the hash table
+ MutexGuard aGuard( rInit.maMutex );
+ WeakMap_Impl::iterator aIt = rInit.maWeakMap.find( pTD->pTypeName->buffer );
+ if( aIt != rInit.maWeakMap.end() && static_cast<void *>((*aIt).second) == static_cast<void *>(pTD) )
+ {
+ // remove only if it contains the same object
+ rInit.maWeakMap.erase( aIt );
+ }
+ }
+
+ typelib_typedescription_destructExtendedMembers( pTD );
+ rtl_uString_release( pTD->pTypeName );
+
+#if OSL_DEBUG_LEVEL > 0
+ switch( pTD->eTypeClass )
+ {
+ case typelib_TypeClass_SEQUENCE:
+ osl_atomic_decrement( &rInit.nIndirectTypeDescriptionCount );
+ break;
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ osl_atomic_decrement( &rInit.nCompoundTypeDescriptionCount );
+ break;
+ case typelib_TypeClass_INTERFACE:
+ osl_atomic_decrement( &rInit.nInterfaceTypeDescriptionCount );
+ break;
+ case typelib_TypeClass_INTERFACE_METHOD:
+ osl_atomic_decrement( &rInit.nInterfaceMethodTypeDescriptionCount );
+ break;
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ osl_atomic_decrement( &rInit.nInterfaceAttributeTypeDescriptionCount );
+ break;
+ case typelib_TypeClass_ENUM:
+ osl_atomic_decrement( &rInit.nEnumTypeDescriptionCount );
+ break;
+ default:
+ osl_atomic_decrement( &rInit.nTypeDescriptionCount );
+ }
+#endif
+
+ freeTypeDescription(pTD);
+}
+
+
+extern "C" void SAL_CALL typelib_typedescription_register(
+ typelib_TypeDescription ** ppNewDescription )
+ SAL_THROW_EXTERN_C()
+{
+ // connect the description with the weak reference
+ TypeDescriptor_Init_Impl &rInit = Init();
+ ClearableMutexGuard aGuard( rInit.maMutex );
+
+ typelib_TypeDescriptionReference * pTDR = nullptr;
+ typelib_typedescriptionreference_getByName( &pTDR, (*ppNewDescription)->pTypeName );
+
+ OSL_ASSERT( (*ppNewDescription)->pWeakRef || TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( (*ppNewDescription)->eTypeClass ) );
+ if( pTDR )
+ {
+ OSL_ASSERT( (*ppNewDescription)->eTypeClass == pTDR->eTypeClass );
+ if( pTDR->pType )
+ {
+ if (TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( pTDR->eTypeClass ))
+ {
+ // pRef->pType->pWeakRef == 0 means that the description is empty
+ if (pTDR->pType->pWeakRef)
+ {
+ if (osl_atomic_increment( &pTDR->pType->nRefCount ) > 1)
+ {
+ // The reference is incremented. The object cannot be destroyed.
+ // Release the guard at the earliest point.
+ aGuard.clear();
+ ::typelib_typedescription_release( *ppNewDescription );
+ *ppNewDescription = pTDR->pType;
+ ::typelib_typedescriptionreference_release( pTDR );
+ return;
+ }
+ // destruction of this type in progress (another thread!)
+ (void)osl_atomic_decrement( &pTDR->pType->nRefCount );
+ }
+ // take new descr
+ pTDR->pType = *ppNewDescription;
+ OSL_ASSERT( ! (*ppNewDescription)->pWeakRef );
+ (*ppNewDescription)->pWeakRef = pTDR;
+ return;
+ }
+ // !reallyWeak
+
+ if ((static_cast<void *>(pTDR) != static_cast<void *>(*ppNewDescription)) && // if different
+ (!pTDR->pType->pWeakRef || // uninit: ref data only set
+ // new one is complete:
+ (!pTDR->pType->bComplete && (*ppNewDescription)->bComplete) ||
+ // new one may be partly initialized interface (except of tables):
+ (typelib_TypeClass_INTERFACE == pTDR->pType->eTypeClass &&
+ !reinterpret_cast<typelib_InterfaceTypeDescription *>(pTDR->pType)->ppAllMembers &&
+ (*reinterpret_cast<typelib_InterfaceTypeDescription **>(ppNewDescription))->ppAllMembers)))
+ {
+ // uninitialized or incomplete
+
+ if (pTDR->pType->pWeakRef) // if init
+ {
+ switch (pTDR->pType->eTypeClass) {
+ case typelib_TypeClass_ENUM:
+ {
+ auto const src = reinterpret_cast<typelib_EnumTypeDescription *>(
+ *ppNewDescription);
+ auto const dst = reinterpret_cast<typelib_EnumTypeDescription *>(
+ pTDR->pType);
+ assert(dst->nEnumValues == 0);
+ assert(dst->ppEnumNames == nullptr);
+ assert(dst->pEnumValues == nullptr);
+ std::swap(src->nEnumValues, dst->nEnumValues);
+ std::swap(src->ppEnumNames, dst->ppEnumNames);
+ std::swap(src->pEnumValues, dst->pEnumValues);
+ break;
+ }
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ auto const src = reinterpret_cast<typelib_CompoundTypeDescription *>(
+ *ppNewDescription);
+ auto const dst = reinterpret_cast<typelib_CompoundTypeDescription *>(
+ pTDR->pType);
+ assert(
+ (dst->pBaseTypeDescription == nullptr)
+ == (src->pBaseTypeDescription == nullptr));
+ assert(dst->nMembers == src->nMembers);
+ assert((dst->pMemberOffsets == nullptr) == (dst->nMembers == 0));
+ assert((dst->ppTypeRefs == nullptr) == (dst->nMembers == 0));
+ assert(dst->ppMemberNames == nullptr);
+ assert(
+ pTDR->pType->eTypeClass != typelib_TypeClass_STRUCT
+ || ((reinterpret_cast<typelib_StructTypeDescription *>(
+ dst)->pParameterizedTypes
+ == nullptr)
+ == (reinterpret_cast<typelib_StructTypeDescription *>(
+ src)->pParameterizedTypes
+ == nullptr)));
+ std::swap(src->ppMemberNames, dst->ppMemberNames);
+ break;
+ }
+ case typelib_TypeClass_INTERFACE:
+ {
+ auto const src = reinterpret_cast<typelib_InterfaceTypeDescription *>(
+ *ppNewDescription);
+ auto const dst = reinterpret_cast<typelib_InterfaceTypeDescription *>(
+ pTDR->pType);
+ assert(
+ (dst->pBaseTypeDescription == nullptr)
+ == (src->pBaseTypeDescription == nullptr));
+ assert(dst->nMembers == 0);
+ assert(dst->ppMembers == nullptr);
+ assert(dst->nAllMembers == 0);
+ assert(dst->ppAllMembers == nullptr);
+ assert(dst->pMapMemberIndexToFunctionIndex == nullptr);
+ assert(dst->nMapFunctionIndexToMemberIndex == 0);
+ assert(dst->pMapFunctionIndexToMemberIndex == nullptr);
+ assert(dst->nBaseTypes == src->nBaseTypes);
+ assert((dst->ppBaseTypes == nullptr) == (src->ppBaseTypes == nullptr));
+ std::swap(src->nMembers, dst->nMembers);
+ std::swap(src->ppMembers, dst->ppMembers);
+ std::swap(src->nAllMembers, dst->nAllMembers);
+ std::swap(src->ppAllMembers, dst->ppAllMembers);
+ std::swap(
+ src->pMapMemberIndexToFunctionIndex,
+ dst->pMapMemberIndexToFunctionIndex);
+ std::swap(
+ src->nMapFunctionIndexToMemberIndex,
+ dst->nMapFunctionIndexToMemberIndex);
+ std::swap(
+ src->pMapFunctionIndexToMemberIndex,
+ dst->pMapFunctionIndexToMemberIndex);
+ break;
+ }
+ default:
+ assert(false); // this cannot happen
+ }
+ }
+ else
+ {
+ // pTDR->pType->pWeakRef == 0 means that the description is empty
+ // description is not weak and the not the same
+ sal_Int32 nSize = getDescriptionSize( (*ppNewDescription)->eTypeClass );
+
+ // copy all specific data for the descriptions
+ memcpy(
+ pTDR->pType +1,
+ *ppNewDescription +1,
+ nSize - sizeof(typelib_TypeDescription) );
+
+ memset(
+ *ppNewDescription +1,
+ 0,
+ nSize - sizeof( typelib_TypeDescription ) );
+ }
+
+ pTDR->pType->bComplete = (*ppNewDescription)->bComplete;
+ pTDR->pType->nSize = (*ppNewDescription)->nSize;
+ pTDR->pType->nAlignment = (*ppNewDescription)->nAlignment;
+
+ if( pTDR->pType->bOnDemand && !(*ppNewDescription)->bOnDemand )
+ {
+ // switch from OnDemand to !OnDemand, so the description must be acquired
+ typelib_typedescription_acquire( pTDR->pType );
+ }
+ else if( !pTDR->pType->bOnDemand && (*ppNewDescription)->bOnDemand )
+ {
+ // switch from !OnDemand to OnDemand, so the description must be released
+ assert(pTDR->pType->nRefCount > 1);
+ // coverity[freed_arg] - pType's nRefCount is > 1 here
+ typelib_typedescription_release( pTDR->pType );
+ }
+
+ pTDR->pType->bOnDemand = (*ppNewDescription)->bOnDemand;
+ // initialized
+ pTDR->pType->pWeakRef = pTDR;
+ }
+
+ typelib_typedescription_release( *ppNewDescription );
+ // pTDR was acquired by getByName(), so it must not be acquired again
+ *ppNewDescription = pTDR->pType;
+ return;
+ }
+ }
+ else if( TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( (*ppNewDescription)->eTypeClass) )
+ {
+ typelib_typedescriptionreference_new(
+ &pTDR, (*ppNewDescription)->eTypeClass, (*ppNewDescription)->pTypeName );
+ }
+ else
+ {
+ pTDR = reinterpret_cast<typelib_TypeDescriptionReference *>(*ppNewDescription);
+
+ // description is the weak itself, so register it
+ rInit.maWeakMap[pTDR->pTypeName->buffer] = pTDR;
+ OSL_ASSERT( static_cast<void *>(*ppNewDescription) == static_cast<void *>(pTDR) );
+ }
+
+ // By default this reference is not really weak. The reference hold the description
+ // and the description hold the reference.
+ if( !(*ppNewDescription)->bOnDemand )
+ {
+ // nor OnDemand so the description must be acquired if registered
+ typelib_typedescription_acquire( *ppNewDescription );
+ }
+
+ pTDR->pType = *ppNewDescription;
+ (*ppNewDescription)->pWeakRef = pTDR;
+ OSL_ASSERT( rtl_ustr_compare( pTDR->pTypeName->buffer, (*ppNewDescription)->pTypeName->buffer ) == 0 );
+ OSL_ASSERT( pTDR->eTypeClass == (*ppNewDescription)->eTypeClass );
+}
+
+
+static bool type_equals(
+ typelib_TypeDescriptionReference const * p1, typelib_TypeDescriptionReference const * p2 )
+{
+ return (p1 == p2 ||
+ (p1->eTypeClass == p2->eTypeClass &&
+ p1->pTypeName->length == p2->pTypeName->length &&
+ rtl_ustr_compare( p1->pTypeName->buffer, p2->pTypeName->buffer ) == 0));
+}
+extern "C" sal_Bool SAL_CALL typelib_typedescription_equals(
+ const typelib_TypeDescription * p1, const typelib_TypeDescription * p2 )
+ SAL_THROW_EXTERN_C()
+{
+ return type_equals(
+ reinterpret_cast<typelib_TypeDescriptionReference const *>(p1), reinterpret_cast<typelib_TypeDescriptionReference const *>(p2) );
+}
+
+
+extern "C" sal_Int32 typelib_typedescription_getAlignedUnoSize(
+ const typelib_TypeDescription * pTypeDescription,
+ sal_Int32 nOffset, sal_Int32 & rMaxIntegralTypeSize )
+ SAL_THROW_EXTERN_C()
+{
+ sal_Int32 nSize;
+ if( pTypeDescription->nSize )
+ {
+ // size and alignment are set
+ rMaxIntegralTypeSize = pTypeDescription->nAlignment;
+ nSize = pTypeDescription->nSize;
+ }
+ else
+ {
+ nSize = 0;
+ rMaxIntegralTypeSize = 1;
+
+ OSL_ASSERT( typelib_TypeClass_TYPEDEF != pTypeDescription->eTypeClass );
+
+ switch( pTypeDescription->eTypeClass )
+ {
+ case typelib_TypeClass_INTERFACE:
+ // FEATURE_INTERFACE
+ nSize = rMaxIntegralTypeSize = sal_Int32(sizeof( void * ));
+ break;
+ case typelib_TypeClass_ENUM:
+ nSize = rMaxIntegralTypeSize = sal_Int32(sizeof( typelib_TypeClass ));
+ break;
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ // FEATURE_EMPTYCLASS
+ {
+ typelib_CompoundTypeDescription const * pTmp = reinterpret_cast<typelib_CompoundTypeDescription const *>(pTypeDescription);
+ sal_Int32 nStructSize = 0;
+ if( pTmp->pBaseTypeDescription )
+ {
+ // inherit structs extends the base struct.
+ nStructSize = pTmp->pBaseTypeDescription->aBase.nSize;
+ rMaxIntegralTypeSize = pTmp->pBaseTypeDescription->aBase.nAlignment;
+ }
+ for( sal_Int32 i = 0; i < pTmp->nMembers; i++ )
+ {
+ typelib_TypeDescription * pMemberType = nullptr;
+ typelib_TypeDescriptionReference * pMemberRef = pTmp->ppTypeRefs[i];
+
+ sal_Int32 nMaxIntegral;
+ if (pMemberRef->eTypeClass == typelib_TypeClass_INTERFACE
+ || pMemberRef->eTypeClass == typelib_TypeClass_SEQUENCE)
+ {
+ nMaxIntegral = sal_Int32(sizeof(void *));
+ nStructSize = newAlignedSize( nStructSize, nMaxIntegral, nMaxIntegral );
+ }
+ else
+ {
+ TYPELIB_DANGER_GET( &pMemberType, pMemberRef );
+ nStructSize = typelib_typedescription_getAlignedUnoSize(
+ pMemberType, nStructSize, nMaxIntegral );
+ TYPELIB_DANGER_RELEASE( pMemberType );
+ }
+ if( nMaxIntegral > rMaxIntegralTypeSize )
+ rMaxIntegralTypeSize = nMaxIntegral;
+ }
+#ifdef __m68k__
+ // Anything that is at least 16 bits wide is aligned on a 16-bit
+ // boundary on the m68k default abi
+ sal_Int32 nMaxAlign = std::min(rMaxIntegralTypeSize, sal_Int32( 2 ));
+ nStructSize = (nStructSize + nMaxAlign -1) / nMaxAlign * nMaxAlign;
+#else
+ // Example: A { double; int; } structure has a size of 16 instead of 10. The
+ // compiler must follow this rule if it is possible to access members in arrays through:
+ // (Element *)((char *)pArray + sizeof( Element ) * ElementPos)
+ nStructSize = (nStructSize + rMaxIntegralTypeSize -1)
+ / rMaxIntegralTypeSize * rMaxIntegralTypeSize;
+#endif
+ nSize += nStructSize;
+ }
+ break;
+ case typelib_TypeClass_SEQUENCE:
+ nSize = rMaxIntegralTypeSize = sal_Int32(sizeof( void * ));
+ break;
+ case typelib_TypeClass_ANY:
+ // FEATURE_ANY
+ nSize = sal_Int32(sizeof( uno_Any ));
+ rMaxIntegralTypeSize = sal_Int32(sizeof( void * ));
+ break;
+ case typelib_TypeClass_TYPE:
+ nSize = rMaxIntegralTypeSize = sal_Int32(sizeof( typelib_TypeDescriptionReference * ));
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ nSize = rMaxIntegralTypeSize = sal_Int32(sizeof( sal_Bool ));
+ break;
+ case typelib_TypeClass_CHAR:
+ nSize = rMaxIntegralTypeSize = sal_Int32(sizeof( sal_Unicode ));
+ break;
+ case typelib_TypeClass_STRING:
+ // FEATURE_STRING
+ nSize = rMaxIntegralTypeSize = sal_Int32(sizeof( rtl_uString * ));
+ break;
+ case typelib_TypeClass_FLOAT:
+ nSize = rMaxIntegralTypeSize = sal_Int32(sizeof( float ));
+ break;
+ case typelib_TypeClass_DOUBLE:
+#ifdef AIX
+ //See previous AIX ifdef comment for an explanation
+ nSize = (sal_Int32)(sizeof(double));
+ rMaxIntegralTypeSize = (sal_Int32)(sizeof(void*));
+#else
+ nSize = rMaxIntegralTypeSize = sal_Int32(sizeof( double ));
+#endif
+ break;
+ case typelib_TypeClass_BYTE:
+ nSize = rMaxIntegralTypeSize = sal_Int32(sizeof( sal_Int8 ));
+ break;
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ nSize = rMaxIntegralTypeSize = sal_Int32(sizeof( sal_Int16 ));
+ break;
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ nSize = rMaxIntegralTypeSize = sal_Int32(sizeof( sal_Int32 ));
+ break;
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ nSize = rMaxIntegralTypeSize = sal_Int32(sizeof( sal_Int64 ));
+ break;
+ case typelib_TypeClass_UNKNOWN:
+ case typelib_TypeClass_SERVICE:
+ case typelib_TypeClass_MODULE:
+ default:
+ OSL_FAIL( "not convertible type" );
+ };
+ }
+
+ return newAlignedSize( nOffset, nSize, rMaxIntegralTypeSize );
+}
+
+
+namespace {
+
+typelib_TypeDescriptionReference ** copyExceptions(
+ sal_Int32 count, typelib_TypeDescriptionReference ** source)
+{
+ typelib_TypeDescriptionReference ** p
+ = new typelib_TypeDescriptionReference *[count];
+ for (sal_Int32 i = 0; i < count; ++i) {
+ p[i] = source[i];
+ typelib_typedescriptionreference_acquire(p[i]);
+ }
+ return p;
+}
+
+bool createDerivedInterfaceMemberDescription(
+ typelib_TypeDescription ** result, OUString const & name,
+ typelib_TypeDescriptionReference * baseRef,
+ typelib_TypeDescription const * base, typelib_TypeDescription * interface,
+ sal_Int32 index, sal_Int32 position)
+{
+ if (!baseRef || !base || !interface)
+ return false;
+
+ switch (base->eTypeClass) {
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ typelib_typedescription_newEmpty(
+ result, typelib_TypeClass_INTERFACE_METHOD, name.pData);
+ typelib_InterfaceMethodTypeDescription const * baseMethod
+ = reinterpret_cast<
+ typelib_InterfaceMethodTypeDescription const * >(base);
+ typelib_InterfaceMethodTypeDescription * newMethod
+ = reinterpret_cast<
+ typelib_InterfaceMethodTypeDescription * >(*result);
+ newMethod->aBase.nPosition = position;
+ newMethod->aBase.pMemberName
+ = baseMethod->aBase.pMemberName;
+ rtl_uString_acquire(
+ newMethod->aBase.pMemberName);
+ newMethod->pReturnTypeRef = baseMethod->pReturnTypeRef;
+ typelib_typedescriptionreference_acquire(
+ newMethod->pReturnTypeRef);
+ newMethod->nParams = baseMethod->nParams;
+ newMethod->pParams = new typelib_MethodParameter[
+ newMethod->nParams];
+ for (sal_Int32 i = 0; i < newMethod->nParams; ++i) {
+ newMethod->pParams[i].pName
+ = baseMethod->pParams[i].pName;
+ rtl_uString_acquire(
+ newMethod->pParams[i].pName);
+ newMethod->pParams[i].pTypeRef
+ = baseMethod->pParams[i].pTypeRef;
+ typelib_typedescriptionreference_acquire(
+ newMethod->pParams[i].pTypeRef);
+ newMethod->pParams[i].bIn = baseMethod->pParams[i].bIn;
+ newMethod->pParams[i].bOut = baseMethod->pParams[i].bOut;
+ }
+ newMethod->nExceptions = baseMethod->nExceptions;
+ newMethod->ppExceptions = copyExceptions(
+ baseMethod->nExceptions, baseMethod->ppExceptions);
+ newMethod->bOneWay = baseMethod->bOneWay;
+ newMethod->pInterface
+ = reinterpret_cast< typelib_InterfaceTypeDescription * >(
+ interface);
+ newMethod->pBaseRef = baseRef;
+ newMethod->nIndex = index;
+ return true;
+ }
+
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ {
+ typelib_typedescription_newEmpty(
+ result, typelib_TypeClass_INTERFACE_ATTRIBUTE, name.pData);
+ typelib_InterfaceAttributeTypeDescription const * baseAttribute
+ = reinterpret_cast<
+ typelib_InterfaceAttributeTypeDescription const * >(base);
+ typelib_InterfaceAttributeTypeDescription * newAttribute
+ = reinterpret_cast<
+ typelib_InterfaceAttributeTypeDescription * >(*result);
+ newAttribute->aBase.nPosition = position;
+ newAttribute->aBase.pMemberName
+ = baseAttribute->aBase.pMemberName;
+ rtl_uString_acquire(newAttribute->aBase.pMemberName);
+ newAttribute->bReadOnly = baseAttribute->bReadOnly;
+ newAttribute->pAttributeTypeRef
+ = baseAttribute->pAttributeTypeRef;
+ typelib_typedescriptionreference_acquire(newAttribute->pAttributeTypeRef);
+ newAttribute->pInterface
+ = reinterpret_cast< typelib_InterfaceTypeDescription * >(
+ interface);
+ newAttribute->pBaseRef = baseRef;
+ newAttribute->nIndex = index;
+ newAttribute->nGetExceptions = baseAttribute->nGetExceptions;
+ newAttribute->ppGetExceptions = copyExceptions(
+ baseAttribute->nGetExceptions,
+ baseAttribute->ppGetExceptions);
+ newAttribute->nSetExceptions = baseAttribute->nSetExceptions;
+ newAttribute->ppSetExceptions = copyExceptions(
+ baseAttribute->nSetExceptions,
+ baseAttribute->ppSetExceptions);
+ return true;
+ }
+
+ default:
+ break;
+ }
+ return false;
+}
+
+}
+
+extern "C" void SAL_CALL typelib_typedescription_getByName(
+ typelib_TypeDescription ** ppRet, rtl_uString * pName )
+ SAL_THROW_EXTERN_C()
+{
+ if( *ppRet )
+ {
+ typelib_typedescription_release( *ppRet );
+ *ppRet = nullptr;
+ }
+
+ static bool bInited = false;
+ TypeDescriptor_Init_Impl &rInit = Init();
+
+ if( !bInited )
+ {
+ // guard against multi thread access
+ MutexGuard aGuard( rInit.maMutex );
+ if( !bInited )
+ {
+ // avoid recursion during the next ...new calls
+ bInited = true;
+
+ typelib_TypeDescription * pType = nullptr;
+ typelib_typedescription_new( &pType, typelib_TypeClass_TYPE, OUString("type").pData, nullptr, 0, nullptr );
+ typelib_typedescription_register( &pType );
+ typelib_typedescription_new( &pType, typelib_TypeClass_VOID, OUString("void").pData, nullptr, 0, nullptr );
+ typelib_typedescription_register( &pType );
+ typelib_typedescription_new( &pType, typelib_TypeClass_BOOLEAN, OUString("boolean").pData, nullptr, 0, nullptr );
+ typelib_typedescription_register( &pType );
+ typelib_typedescription_new( &pType, typelib_TypeClass_CHAR, OUString("char").pData, nullptr, 0, nullptr );
+ typelib_typedescription_register( &pType );
+ typelib_typedescription_new( &pType, typelib_TypeClass_BYTE, OUString("byte").pData, nullptr, 0, nullptr );
+ typelib_typedescription_register( &pType );
+ typelib_typedescription_new( &pType, typelib_TypeClass_STRING, OUString("string").pData, nullptr, 0, nullptr );
+ typelib_typedescription_register( &pType );
+ typelib_typedescription_new( &pType, typelib_TypeClass_SHORT, OUString("short").pData, nullptr, 0, nullptr );
+ typelib_typedescription_register( &pType );
+ typelib_typedescription_new( &pType, typelib_TypeClass_UNSIGNED_SHORT, OUString("unsigned short").pData, nullptr, 0, nullptr );
+ typelib_typedescription_register( &pType );
+ typelib_typedescription_new( &pType, typelib_TypeClass_LONG, OUString("long").pData, nullptr, 0, nullptr );
+ typelib_typedescription_register( &pType );
+ typelib_typedescription_new( &pType, typelib_TypeClass_UNSIGNED_LONG, OUString("unsigned long").pData, nullptr, 0, nullptr );
+ typelib_typedescription_register( &pType );
+ typelib_typedescription_new( &pType, typelib_TypeClass_HYPER, OUString("hyper").pData, nullptr, 0, nullptr );
+ typelib_typedescription_register( &pType );
+ typelib_typedescription_new( &pType, typelib_TypeClass_UNSIGNED_HYPER, OUString("unsigned hyper").pData, nullptr, 0, nullptr );
+ typelib_typedescription_register( &pType );
+ typelib_typedescription_new( &pType, typelib_TypeClass_FLOAT, OUString("float").pData, nullptr, 0, nullptr );
+ typelib_typedescription_register( &pType );
+ typelib_typedescription_new( &pType, typelib_TypeClass_DOUBLE, OUString("double").pData, nullptr, 0, nullptr );
+ typelib_typedescription_register( &pType );
+ typelib_typedescription_new( &pType, typelib_TypeClass_ANY, OUString("any").pData, nullptr, 0, nullptr );
+ typelib_typedescription_register( &pType );
+ typelib_typedescription_release( pType );
+ }
+ }
+
+ typelib_TypeDescriptionReference * pTDR = nullptr;
+ typelib_typedescriptionreference_getByName( &pTDR, pName );
+ if( pTDR )
+ {
+ {
+ // guard against multi thread access
+ MutexGuard aGuard( rInit.maMutex );
+ // pTDR->pType->pWeakRef == 0 means that the description is empty
+ if( pTDR->pType && pTDR->pType->pWeakRef )
+ {
+ typelib_typedescription_acquire( pTDR->pType );
+ *ppRet = pTDR->pType;
+ }
+ }
+ typelib_typedescriptionreference_release( pTDR );
+ }
+
+ if (nullptr != *ppRet)
+ return;
+
+ // check for sequence
+ OUString const & name = OUString::unacquired( &pName );
+ if (2 < name.getLength() && '[' == name[ 0 ])
+ {
+ OUString element_name( name.copy( 2 ) );
+ typelib_TypeDescription * element_td = nullptr;
+ typelib_typedescription_getByName( &element_td, element_name.pData );
+ if (nullptr != element_td)
+ {
+ typelib_typedescription_new(
+ ppRet, typelib_TypeClass_SEQUENCE, pName, element_td->pWeakRef, 0, nullptr );
+ // register?
+ typelib_typedescription_release( element_td );
+ }
+ }
+ if (nullptr == *ppRet)
+ {
+ // Check for derived interface member type:
+ sal_Int32 i1 = name.lastIndexOf(":@");
+ if (i1 >= 0) {
+ sal_Int32 i2 = i1 + RTL_CONSTASCII_LENGTH(":@");
+ sal_Int32 i3 = name.indexOf(',', i2);
+ if (i3 >= 0) {
+ sal_Int32 i4 = name.indexOf(':', i3);
+ if (i4 >= 0) {
+ typelib_TypeDescriptionReference * pBaseRef = nullptr;
+ typelib_TypeDescription * pBase = nullptr;
+ typelib_TypeDescription * pInterface = nullptr;
+ typelib_typedescriptionreference_getByName(
+ &pBaseRef, name.copy(0, i1).pData);
+ if (pBaseRef != nullptr) {
+ typelib_typedescriptionreference_getDescription(
+ &pBase, pBaseRef);
+ }
+ typelib_typedescription_getByName(
+ &pInterface, name.copy(i4 + 1).pData);
+ if (!createDerivedInterfaceMemberDescription(
+ ppRet, name, pBaseRef, pBase, pInterface,
+ o3tl::toInt32(name.subView(i2, i3 - i2)),
+ o3tl::toInt32(name.subView(i3 + 1, i4 - i3 - 1))))
+ {
+ if (pInterface != nullptr) {
+ typelib_typedescription_release(pInterface);
+ }
+ if (pBase != nullptr) {
+ typelib_typedescription_release(pBase);
+ }
+ if (pBaseRef != nullptr) {
+ typelib_typedescriptionreference_release(
+ pBaseRef);
+ }
+ }
+ }
+ }
+ }
+ }
+ if (nullptr == *ppRet)
+ {
+ // on demand access
+ rInit.callChain( ppRet, pName );
+ }
+
+ if( !(*ppRet) )
+ return;
+
+ // typedescription found
+ if (typelib_TypeClass_TYPEDEF == (*ppRet)->eTypeClass)
+ {
+ typelib_TypeDescription * pTD = nullptr;
+ typelib_typedescriptionreference_getDescription(
+ &pTD, reinterpret_cast<typelib_IndirectTypeDescription *>(*ppRet)->pType );
+ typelib_typedescription_release( *ppRet );
+ *ppRet = pTD;
+ }
+ else
+ {
+ // set to on demand
+ (*ppRet)->bOnDemand = true;
+ // The type description is hold by the reference until
+ // on demand is activated.
+ typelib_typedescription_register( ppRet );
+
+ // insert into the cache
+ MutexGuard aGuard( rInit.maMutex );
+ if( rInit.maCache.size() >= nCacheSize )
+ {
+ typelib_typedescription_release( rInit.maCache.front() );
+ rInit.maCache.pop_front();
+ }
+ // descriptions in the cache must be acquired!
+ typelib_typedescription_acquire( *ppRet );
+ rInit.maCache.push_back( *ppRet );
+ }
+}
+
+extern "C" void SAL_CALL typelib_typedescriptionreference_newByAsciiName(
+ typelib_TypeDescriptionReference ** ppTDR,
+ typelib_TypeClass eTypeClass,
+ const char * pTypeName )
+ SAL_THROW_EXTERN_C()
+{
+ OUString aTypeName( OUString::createFromAscii( pTypeName ) );
+ typelib_typedescriptionreference_new( ppTDR, eTypeClass, aTypeName.pData );
+}
+
+extern "C" void SAL_CALL typelib_typedescriptionreference_new(
+ typelib_TypeDescriptionReference ** ppTDR,
+ typelib_TypeClass eTypeClass, rtl_uString * pTypeName )
+ SAL_THROW_EXTERN_C()
+{
+ TypeDescriptor_Init_Impl &rInit = Init();
+ if( eTypeClass == typelib_TypeClass_TYPEDEF )
+ {
+ // on demand access
+ typelib_TypeDescription * pRet = nullptr;
+ rInit.callChain( &pRet, pTypeName );
+ if( pRet )
+ {
+ // typedescription found
+ if (typelib_TypeClass_TYPEDEF == pRet->eTypeClass)
+ {
+ typelib_typedescriptionreference_acquire(
+ reinterpret_cast<typelib_IndirectTypeDescription *>(pRet)->pType );
+ if (*ppTDR)
+ typelib_typedescriptionreference_release( *ppTDR );
+ *ppTDR = reinterpret_cast<typelib_IndirectTypeDescription *>(pRet)->pType;
+ typelib_typedescription_release( pRet );
+ }
+ else
+ {
+ // set to on demand
+ pRet->bOnDemand = true;
+ // The type description is hold by the reference until
+ // on demand is activated.
+ typelib_typedescription_register( &pRet );
+
+ // insert into the cache
+ MutexGuard aGuard( rInit.maMutex );
+ if( rInit.maCache.size() >= nCacheSize )
+ {
+ typelib_typedescription_release( rInit.maCache.front() );
+ rInit.maCache.pop_front();
+ }
+ rInit.maCache.push_back( pRet );
+ // pRet kept acquired for cache
+
+ typelib_typedescriptionreference_acquire( pRet->pWeakRef );
+ if (*ppTDR)
+ typelib_typedescriptionreference_release( *ppTDR );
+ *ppTDR = pRet->pWeakRef;
+ }
+ }
+ else if (*ppTDR)
+ {
+ SAL_INFO("cppu.typelib", "typedef not found : " << pTypeName);
+ typelib_typedescriptionreference_release( *ppTDR );
+ *ppTDR = nullptr;
+ }
+ return;
+ }
+
+ MutexGuard aGuard( rInit.maMutex );
+ typelib_typedescriptionreference_getByName( ppTDR, pTypeName );
+ if( *ppTDR )
+ return;
+
+ if( TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( eTypeClass ) )
+ {
+ typelib_TypeDescriptionReference * pTDR = new typelib_TypeDescriptionReference;
+#if OSL_DEBUG_LEVEL > 0
+ osl_atomic_increment( &rInit.nTypeDescriptionReferenceCount );
+#endif
+ pTDR->nRefCount = 1;
+ pTDR->nStaticRefCount = 0;
+ pTDR->eTypeClass = eTypeClass;
+ pTDR->pUniqueIdentifier = nullptr;
+ pTDR->pReserved = nullptr;
+ pTDR->pTypeName = pTypeName;
+ rtl_uString_acquire( pTDR->pTypeName );
+ pTDR->pType = nullptr;
+ *ppTDR = pTDR;
+ }
+ else
+ {
+ typelib_typedescription_newEmpty( reinterpret_cast<typelib_TypeDescription ** >(ppTDR), eTypeClass, pTypeName );
+ // description will be registered but not acquired
+ (*reinterpret_cast<typelib_TypeDescription **>(ppTDR))->bOnDemand = true;
+ (*reinterpret_cast<typelib_TypeDescription **>(ppTDR))->bComplete = false;
+ }
+
+ // Heavy hack, the const sal_Unicode * is hold by the typedescription reference
+ // not registered
+ rInit.maWeakMap[ (*ppTDR)->pTypeName->buffer ] = *ppTDR;
+}
+
+
+extern "C" void SAL_CALL typelib_typedescriptionreference_acquire(
+ typelib_TypeDescriptionReference * pRef )
+ SAL_THROW_EXTERN_C()
+{
+ osl_atomic_increment( &pRef->nRefCount );
+}
+
+
+extern "C" void SAL_CALL typelib_typedescriptionreference_release(
+ typelib_TypeDescriptionReference * pRef )
+ SAL_THROW_EXTERN_C()
+{
+ // Is it a type description?
+ if( TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( pRef->eTypeClass ) )
+ {
+ if( ! osl_atomic_decrement( &pRef->nRefCount ) )
+ {
+ TypeDescriptor_Init_Impl &rInit = Init();
+ MutexGuard aGuard( rInit.maMutex );
+ WeakMap_Impl::iterator aIt = rInit.maWeakMap.find( pRef->pTypeName->buffer );
+ if( aIt != rInit.maWeakMap.end() && (*aIt).second == pRef )
+ {
+ // remove only if it contains the same object
+ rInit.maWeakMap.erase( aIt );
+ }
+
+ rtl_uString_release( pRef->pTypeName );
+ OSL_ASSERT( pRef->pType == nullptr );
+#if OSL_DEBUG_LEVEL > 0
+ osl_atomic_decrement( &rInit.nTypeDescriptionReferenceCount );
+#endif
+ delete pRef;
+ }
+ }
+ else
+ {
+ typelib_typedescription_release( reinterpret_cast<typelib_TypeDescription *>(pRef) );
+ }
+}
+
+
+extern "C" void SAL_CALL typelib_typedescriptionreference_getDescription(
+ typelib_TypeDescription ** ppRet, typelib_TypeDescriptionReference * pRef )
+ SAL_THROW_EXTERN_C()
+{
+ if( *ppRet )
+ {
+ typelib_typedescription_release( *ppRet );
+ *ppRet = nullptr;
+ }
+
+ if( !TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( pRef->eTypeClass ) && pRef->pType && pRef->pType->pWeakRef )
+ {
+ // reference is a description and initialized
+ osl_atomic_increment( &reinterpret_cast<typelib_TypeDescription *>(pRef)->nRefCount );
+ *ppRet = reinterpret_cast<typelib_TypeDescription *>(pRef);
+ return;
+ }
+
+ {
+ MutexGuard aGuard( Init().maMutex );
+ // pRef->pType->pWeakRef == 0 means that the description is empty
+ if( pRef->pType && pRef->pType->pWeakRef )
+ {
+ sal_Int32 n = osl_atomic_increment( &pRef->pType->nRefCount );
+ if( n > 1 )
+ {
+ // The reference is incremented. The object cannot be destroyed.
+ // Release the guard at the earliest point.
+ *ppRet = pRef->pType;
+ return;
+ }
+ (void)osl_atomic_decrement( &pRef->pType->nRefCount );
+ // destruction of this type in progress (another thread!)
+ // no access through this weak reference
+ pRef->pType = nullptr;
+ }
+ }
+
+ typelib_typedescription_getByName( ppRet, pRef->pTypeName );
+ OSL_ASSERT( !*ppRet || rtl_ustr_compare( pRef->pTypeName->buffer, (*ppRet)->pTypeName->buffer ) == 0 );
+ OSL_ASSERT( !*ppRet || pRef->eTypeClass == (*ppRet)->eTypeClass );
+ OSL_ASSERT( !*ppRet || pRef == (*ppRet)->pWeakRef );
+ pRef->pType = *ppRet;
+}
+
+
+extern "C" void typelib_typedescriptionreference_getByName(
+ typelib_TypeDescriptionReference ** ppRet, rtl_uString const * pName )
+ SAL_THROW_EXTERN_C()
+{
+ if( *ppRet )
+ {
+ typelib_typedescriptionreference_release( *ppRet );
+ *ppRet = nullptr;
+ }
+ TypeDescriptor_Init_Impl &rInit = Init();
+
+ MutexGuard aGuard( rInit.maMutex );
+ WeakMap_Impl::const_iterator aIt = rInit.maWeakMap.find( pName->buffer );
+ if( aIt == rInit.maWeakMap.end() )
+ return;
+
+ sal_Int32 n = osl_atomic_increment( &(*aIt).second->nRefCount );
+ if( n > 1 )
+ {
+ // The reference is incremented. The object cannot be destroyed.
+ // Release the guard at the earliest point.
+ *ppRet = (*aIt).second;
+ }
+ else
+ {
+ // destruction of this type in progress (another thread!)
+ // no access through this weak reference
+ (void)osl_atomic_decrement( &(*aIt).second->nRefCount );
+ }
+}
+
+
+extern "C" sal_Bool SAL_CALL typelib_typedescriptionreference_equals(
+ const typelib_TypeDescriptionReference * p1,
+ const typelib_TypeDescriptionReference * p2 )
+ SAL_THROW_EXTERN_C()
+{
+ return (p1 == p2 ||
+ (p1->eTypeClass == p2->eTypeClass &&
+ p1->pTypeName->length == p2->pTypeName->length &&
+ rtl_ustr_compare( p1->pTypeName->buffer, p2->pTypeName->buffer ) == 0));
+}
+
+
+extern "C" void SAL_CALL typelib_typedescriptionreference_assign(
+ typelib_TypeDescriptionReference ** ppDest,
+ typelib_TypeDescriptionReference * pSource )
+ SAL_THROW_EXTERN_C()
+{
+ if (*ppDest != pSource)
+ {
+ ::typelib_typedescriptionreference_acquire( pSource );
+ ::typelib_typedescriptionreference_release( *ppDest );
+ *ppDest = pSource;
+ }
+}
+
+
+extern "C" void SAL_CALL typelib_setCacheSize( sal_Int32 )
+ SAL_THROW_EXTERN_C()
+{
+}
+
+
+const bool s_aAssignableFromTab[11][11] =
+{
+ /* from CH, BO, BY, SH, US, LO, UL, HY, UH, FL, DO */
+/* TypeClass_CHAR */ { true, false, false, false, false, false, false, false, false, false, false },
+/* TypeClass_BOOLEAN */ { false, true, false, false, false, false, false, false, false, false, false },
+/* TypeClass_BYTE */ { false, false, true, false, false, false, false, false, false, false, false },
+/* TypeClass_SHORT */ { false, false, true, true, true, false, false, false, false, false, false },
+/* TypeClass_UNSIGNED_SHORT */ { false, false, true, true, true, false, false, false, false, false, false },
+/* TypeClass_LONG */ { false, false, true, true, true, true, true, false, false, false, false },
+/* TypeClass_UNSIGNED_LONG */ { false, false, true, true, true, true, true, false, false, false, false },
+/* TypeClass_HYPER */ { false, false, true, true, true, true, true, true, true, false, false },
+/* TypeClass_UNSIGNED_HYPER */ { false, false, true, true, true, true, true, true, true, false, false },
+/* TypeClass_FLOAT */ { false, false, true, true, true, false, false, false, false, true, false },
+/* TypeClass_DOUBLE */ { false, false, true, true, true, true, true, false, false, true, true }
+};
+
+
+extern "C" sal_Bool SAL_CALL typelib_typedescriptionreference_isAssignableFrom(
+ typelib_TypeDescriptionReference * pAssignable,
+ typelib_TypeDescriptionReference * pFrom )
+ SAL_THROW_EXTERN_C()
+{
+ if (!pAssignable || !pFrom)
+ return false;
+
+ typelib_TypeClass eAssignable = pAssignable->eTypeClass;
+ typelib_TypeClass eFrom = pFrom->eTypeClass;
+
+ if (eAssignable == typelib_TypeClass_ANY) // anything can be assigned to an any .)
+ return true;
+ if (eAssignable == eFrom)
+ {
+ if (type_equals( pAssignable, pFrom )) // first shot
+ {
+ return true;
+ }
+ switch (eAssignable)
+ {
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ typelib_TypeDescription * pFromDescr = nullptr;
+ TYPELIB_DANGER_GET( &pFromDescr, pFrom );
+ if (!reinterpret_cast<typelib_CompoundTypeDescription *>(pFromDescr)->pBaseTypeDescription)
+ {
+ TYPELIB_DANGER_RELEASE( pFromDescr );
+ return false;
+ }
+ bool bRet = typelib_typedescriptionreference_isAssignableFrom(
+ pAssignable,
+ reinterpret_cast<typelib_CompoundTypeDescription *>(pFromDescr)->pBaseTypeDescription->aBase.pWeakRef );
+ TYPELIB_DANGER_RELEASE( pFromDescr );
+ return bRet;
+ }
+ case typelib_TypeClass_INTERFACE:
+ {
+ typelib_TypeDescription * pFromDescr = nullptr;
+ TYPELIB_DANGER_GET( &pFromDescr, pFrom );
+ typelib_InterfaceTypeDescription * pFromIfc
+ = reinterpret_cast<
+ typelib_InterfaceTypeDescription * >(pFromDescr);
+ bool bRet = false;
+ for (sal_Int32 i = 0; i < pFromIfc->nBaseTypes; ++i) {
+ if (typelib_typedescriptionreference_isAssignableFrom(
+ pAssignable,
+ pFromIfc->ppBaseTypes[i]->aBase.pWeakRef))
+ {
+ bRet = true;
+ break;
+ }
+ }
+ TYPELIB_DANGER_RELEASE( pFromDescr );
+ return bRet;
+ }
+ default:
+ {
+ return false;
+ }
+ }
+ }
+ return (eAssignable >= typelib_TypeClass_CHAR && eAssignable <= typelib_TypeClass_DOUBLE &&
+ eFrom >= typelib_TypeClass_CHAR && eFrom <= typelib_TypeClass_DOUBLE &&
+ s_aAssignableFromTab[eAssignable-1][eFrom-1]);
+}
+
+extern "C" sal_Bool SAL_CALL typelib_typedescription_isAssignableFrom(
+ typelib_TypeDescription * pAssignable,
+ typelib_TypeDescription * pFrom )
+ SAL_THROW_EXTERN_C()
+{
+ return typelib_typedescriptionreference_isAssignableFrom(
+ pAssignable->pWeakRef, pFrom->pWeakRef );
+}
+
+
+extern "C" sal_Bool SAL_CALL typelib_typedescription_complete(
+ typelib_TypeDescription ** ppTypeDescr )
+ SAL_THROW_EXTERN_C()
+{
+ return complete(ppTypeDescr, true);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/typelib/typelib.hxx b/cppu/source/typelib/typelib.hxx
new file mode 100644
index 000000000..b62e763de
--- /dev/null
+++ b/cppu/source/typelib/typelib.hxx
@@ -0,0 +1,45 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <rtl/ustring.h>
+#include <sal/types.h>
+#include <typelib/typeclass.h>
+#include <typelib/typedescription.h>
+
+extern "C" sal_Int32 typelib_typedescription_getAlignedUnoSize(
+ const typelib_TypeDescription * pTypeDescription,
+ sal_Int32 nOffset,
+ sal_Int32 & rMaxIntegralTypeSize )
+ SAL_THROW_EXTERN_C();
+
+
+extern "C" void typelib_typedescription_newEmpty(
+ typelib_TypeDescription ** ppRet,
+ typelib_TypeClass eTypeClass,
+ rtl_uString * pTypeName )
+ SAL_THROW_EXTERN_C();
+
+extern "C" void typelib_typedescriptionreference_getByName(
+ typelib_TypeDescriptionReference ** ppRet,
+ rtl_uString const * pName )
+ SAL_THROW_EXTERN_C();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/EnvDcp.cxx b/cppu/source/uno/EnvDcp.cxx
new file mode 100644
index 000000000..c5597dec4
--- /dev/null
+++ b/cppu/source/uno/EnvDcp.cxx
@@ -0,0 +1,43 @@
+/* -*- 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 <uno/EnvDcp.h>
+
+
+void uno_EnvDcp_getTypeName(rtl_uString const * pEnvDcp, rtl_uString ** ppEnvTypeName)
+{
+ sal_Int32 colIdx = rtl_ustr_indexOfChar_WithLength(pEnvDcp->buffer, pEnvDcp->length, ':');
+ if (colIdx >= 0)
+ rtl_uString_newFromStr_WithLength(ppEnvTypeName, pEnvDcp->buffer, colIdx);
+
+ else
+ rtl_uString_newFromStr(ppEnvTypeName, pEnvDcp->buffer);
+}
+
+void uno_EnvDcp_getPurpose(rtl_uString const * pEnvDcp, rtl_uString ** ppEnvPurpose)
+{
+ sal_Int32 colIdx = rtl_ustr_indexOfChar_WithLength(pEnvDcp->buffer, pEnvDcp->length, ':');
+ if (colIdx >= 0)
+ rtl_uString_newFromStr_WithLength(ppEnvPurpose, pEnvDcp->buffer + colIdx, pEnvDcp->length - colIdx);
+
+ else
+ rtl_uString_new(ppEnvPurpose);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/EnvStack.cxx b/cppu/source/uno/EnvStack.cxx
new file mode 100644
index 000000000..34fea77f4
--- /dev/null
+++ b/cppu/source/uno/EnvStack.cxx
@@ -0,0 +1,382 @@
+/* -*- 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 <uno/environment.hxx>
+#include <uno/lbnames.h>
+
+#include <cppu/EnvDcp.hxx>
+#include <cppu/Enterable.hxx>
+
+#include <osl/thread.h>
+#include <osl/thread.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <mutex>
+#include <unordered_map>
+
+using namespace com::sun::star;
+
+namespace {
+
+struct oslThreadIdentifier_equal
+{
+ bool operator()(oslThreadIdentifier s1, oslThreadIdentifier s2) const;
+};
+
+}
+
+bool oslThreadIdentifier_equal::operator()(oslThreadIdentifier s1, oslThreadIdentifier s2) const
+{
+ bool result = s1 == s2;
+
+ return result;
+}
+
+namespace {
+
+struct oslThreadIdentifier_hash
+{
+ size_t operator()(oslThreadIdentifier s1) const;
+};
+
+}
+
+size_t oslThreadIdentifier_hash::operator()(oslThreadIdentifier s1) const
+{
+ return s1;
+}
+
+typedef std::unordered_map<oslThreadIdentifier,
+ uno_Environment *,
+ oslThreadIdentifier_hash,
+ oslThreadIdentifier_equal> ThreadMap;
+
+namespace
+{
+ std::mutex s_threadMap_mutex;
+ ThreadMap s_threadMap;
+}
+
+static void s_setCurrent(uno_Environment * pEnv)
+{
+ oslThreadIdentifier threadId = osl::Thread::getCurrentIdentifier();
+
+ std::scoped_lock guard(s_threadMap_mutex);
+ if (pEnv)
+ {
+ s_threadMap[threadId] = pEnv;
+ }
+ else
+ {
+ ThreadMap::iterator iEnv = s_threadMap.find(threadId);
+ if( iEnv != s_threadMap.end())
+ s_threadMap.erase(iEnv);
+ }
+}
+
+static uno_Environment * s_getCurrent()
+{
+ uno_Environment * pEnv = nullptr;
+
+ oslThreadIdentifier threadId = osl::Thread::getCurrentIdentifier();
+
+ std::scoped_lock guard(s_threadMap_mutex);
+ ThreadMap::iterator iEnv = s_threadMap.find(threadId);
+ if(iEnv != s_threadMap.end())
+ pEnv = iEnv->second;
+
+ return pEnv;
+}
+
+
+extern "C" void SAL_CALL uno_getCurrentEnvironment(uno_Environment ** ppEnv, rtl_uString * pTypeName)
+ SAL_THROW_EXTERN_C()
+{
+ if (*ppEnv)
+ {
+ (*ppEnv)->release(*ppEnv);
+ *ppEnv = nullptr;
+ }
+
+ OUString currPurpose;
+
+ uno_Environment * pCurrEnv = s_getCurrent();
+ if (pCurrEnv) // no environment means no purpose
+ currPurpose = cppu::EnvDcp::getPurpose(pCurrEnv->pTypeName);
+
+ if (pTypeName && rtl_uString_getLength(pTypeName))
+ {
+ OUString envDcp = OUString::unacquired(&pTypeName) + currPurpose;
+
+ uno_getEnvironment(ppEnv, envDcp.pData, nullptr);
+ }
+ else
+ {
+ if (pCurrEnv)
+ {
+ *ppEnv = pCurrEnv;
+ (*ppEnv)->acquire(*ppEnv);
+ }
+ else
+ {
+ OUString uno_envDcp(UNO_LB_UNO);
+ uno_getEnvironment(ppEnv, uno_envDcp.pData, nullptr);
+ }
+ }
+}
+
+static OUString s_getPrefix(std::u16string_view str1, std::u16string_view str2)
+{
+ sal_Int32 nIndex1 = 0;
+ sal_Int32 nIndex2 = 0;
+ sal_Int32 sim = 0;
+
+ std::u16string_view token1;
+ std::u16string_view token2;
+
+ do
+ {
+ token1 = o3tl::getToken(str1, 0, ':', nIndex1);
+ token2 = o3tl::getToken(str2, 0, ':', nIndex2);
+
+ if (token1 == token2)
+ sim += token1.size() + 1;
+ }
+ while(nIndex1 == nIndex2 && nIndex1 >= 0 && token1 == token2);
+
+ OUString result;
+
+ if (sim)
+ result = str1.substr(0, sim - 1);
+
+ return result;
+}
+
+static int s_getNextEnv(uno_Environment ** ppEnv, uno_Environment * pCurrEnv, uno_Environment * pTargetEnv)
+{
+ int res = 0;
+
+ std::u16string_view nextPurpose;
+
+ OUString currPurpose;
+ if (pCurrEnv)
+ currPurpose = cppu::EnvDcp::getPurpose(pCurrEnv->pTypeName);
+
+ OUString targetPurpose;
+ if (pTargetEnv)
+ targetPurpose = cppu::EnvDcp::getPurpose(pTargetEnv->pTypeName);
+
+ OUString intermPurpose(s_getPrefix(currPurpose, targetPurpose));
+ if (currPurpose.getLength() > intermPurpose.getLength())
+ {
+ sal_Int32 idx = currPurpose.lastIndexOf(':');
+ nextPurpose = currPurpose.subView(0, idx);
+
+ res = -1;
+ }
+ else if (intermPurpose.getLength() < targetPurpose.getLength())
+ {
+ sal_Int32 idx = targetPurpose.indexOf(':', intermPurpose.getLength() + 1);
+ if (idx == -1)
+ nextPurpose = targetPurpose;
+
+ else
+ nextPurpose = targetPurpose.subView(0, idx);
+
+ res = 1;
+ }
+
+ if (!nextPurpose.empty())
+ {
+ OUString next_envDcp = OUString::Concat(UNO_LB_UNO) + nextPurpose;
+ uno_getEnvironment(ppEnv, next_envDcp.pData, nullptr);
+ }
+ else
+ {
+ if (*ppEnv)
+ (*ppEnv)->release(*ppEnv);
+
+ *ppEnv = nullptr;
+ }
+
+ return res;
+}
+
+extern "C" { static void s_pull(va_list * pParam)
+{
+ uno_EnvCallee * pCallee = va_arg(*pParam, uno_EnvCallee *);
+ va_list * pXparam = va_arg(*pParam, va_list *);
+
+ pCallee(pXparam);
+}}
+
+static void s_callInto_v(uno_Environment * pEnv, uno_EnvCallee * pCallee, va_list * pParam)
+{
+ cppu::Enterable * pEnterable = static_cast<cppu::Enterable *>(pEnv->pReserved);
+ if (pEnterable)
+ pEnterable->callInto(s_pull, pCallee, pParam);
+
+ else
+ pCallee(pParam);
+}
+
+static void s_callInto(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...)
+{
+ va_list param;
+
+ va_start(param, pCallee);
+ s_callInto_v(pEnv, pCallee, &param);
+ va_end(param);
+}
+
+static void s_callOut_v(uno_Environment * pEnv, uno_EnvCallee * pCallee, va_list * pParam)
+{
+ cppu::Enterable * pEnterable = static_cast<cppu::Enterable *>(pEnv->pReserved);
+ if (pEnterable)
+ pEnterable->callOut_v(pCallee, pParam);
+
+ else
+ pCallee(pParam);
+}
+
+static void s_callOut(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...)
+{
+ va_list param;
+
+ va_start(param, pCallee);
+ s_callOut_v(pEnv, pCallee, &param);
+ va_end(param);
+}
+
+static void s_environment_invoke_v(uno_Environment *, uno_Environment *, uno_EnvCallee *, va_list *);
+
+extern "C" { static void s_environment_invoke_vv(va_list * pParam)
+{
+ uno_Environment * pCurrEnv = va_arg(*pParam, uno_Environment *);
+ uno_Environment * pTargetEnv = va_arg(*pParam, uno_Environment *);
+ uno_EnvCallee * pCallee = va_arg(*pParam, uno_EnvCallee *);
+ va_list * pXparam = va_arg(*pParam, va_list *);
+
+ s_environment_invoke_v(pCurrEnv, pTargetEnv, pCallee, pXparam);
+}}
+
+static void s_environment_invoke_v(uno_Environment * pCurrEnv, uno_Environment * pTargetEnv, uno_EnvCallee * pCallee, va_list * pParam)
+{
+ uno_Environment * pNextEnv = nullptr;
+ switch(s_getNextEnv(&pNextEnv, pCurrEnv, pTargetEnv))
+ {
+ case -1:
+ s_setCurrent(pNextEnv);
+ s_callOut(pCurrEnv, s_environment_invoke_vv, pNextEnv, pTargetEnv, pCallee, pParam);
+ s_setCurrent(pCurrEnv);
+ break;
+
+ case 0: {
+ uno_Environment * hld = s_getCurrent();
+ s_setCurrent(pCurrEnv);
+ pCallee(pParam);
+ s_setCurrent(hld);
+ }
+ break;
+
+ case 1:
+ s_setCurrent(pNextEnv);
+ s_callInto(pNextEnv, s_environment_invoke_vv, pNextEnv, pTargetEnv, pCallee, pParam);
+ s_setCurrent(pCurrEnv);
+ break;
+ }
+
+ if (pNextEnv)
+ pNextEnv->release(pNextEnv);
+}
+
+extern "C" void SAL_CALL uno_Environment_invoke_v(uno_Environment * pTargetEnv, uno_EnvCallee * pCallee, va_list * pParam)
+ SAL_THROW_EXTERN_C()
+{
+ s_environment_invoke_v(s_getCurrent(), pTargetEnv, pCallee, pParam);
+}
+
+extern "C" void SAL_CALL uno_Environment_invoke(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...)
+ SAL_THROW_EXTERN_C()
+{
+ va_list param;
+
+ va_start(param, pCallee);
+ uno_Environment_invoke_v(pEnv, pCallee, &param);
+ va_end(param);
+}
+
+extern "C" void SAL_CALL uno_Environment_enter(uno_Environment * pTargetEnv)
+ SAL_THROW_EXTERN_C()
+{
+ uno_Environment * pNextEnv = nullptr;
+ uno_Environment * pCurrEnv = s_getCurrent();
+
+ int res;
+ while ( (res = s_getNextEnv(&pNextEnv, pCurrEnv, pTargetEnv)) != 0)
+ {
+ cppu::Enterable * pEnterable;
+
+ switch(res)
+ {
+ case -1:
+ pEnterable = static_cast<cppu::Enterable *>(pCurrEnv->pReserved);
+ if (pEnterable)
+ pEnterable->leave();
+ pCurrEnv->release(pCurrEnv);
+ break;
+
+ case 1:
+ pNextEnv->acquire(pNextEnv);
+ pEnterable = static_cast<cppu::Enterable *>(pNextEnv->pReserved);
+ if (pEnterable)
+ pEnterable->enter();
+ break;
+ }
+
+ s_setCurrent(pNextEnv);
+ pCurrEnv = pNextEnv;
+ }
+}
+
+int SAL_CALL uno_Environment_isValid(uno_Environment * pEnv, rtl_uString ** pReason)
+ SAL_THROW_EXTERN_C()
+{
+ int result = 1;
+
+ OUString typeName(cppu::EnvDcp::getTypeName(pEnv->pTypeName));
+ if (typeName == UNO_LB_UNO)
+ {
+ cppu::Enterable * pEnterable = static_cast<cppu::Enterable *>(pEnv->pReserved);
+ if (pEnterable)
+ result = pEnterable->isValid(reinterpret_cast<OUString *>(pReason));
+ }
+ else
+ {
+ OUString envDcp = UNO_LB_UNO + cppu::EnvDcp::getPurpose(pEnv->pTypeName);
+
+ uno::Environment env(envDcp);
+
+ result = env.isValid(reinterpret_cast<OUString *>(pReason));
+ }
+
+ return result;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/IdentityMapping.cxx b/cppu/source/uno/IdentityMapping.cxx
new file mode 100644
index 000000000..32ec32c07
--- /dev/null
+++ b/cppu/source/uno/IdentityMapping.cxx
@@ -0,0 +1,105 @@
+/* -*- 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 "IdentityMapping.hxx"
+
+#include <typelib/typedescription.h>
+#include <uno/mapping.h>
+#include <uno/environment.hxx>
+#include <utility>
+
+#include <osl/interlck.h>
+
+
+using namespace ::com::sun::star;
+
+namespace {
+
+struct IdentityMapping : public uno_Mapping
+{
+ sal_Int32 m_nRef;
+ uno::Environment m_env;
+
+ explicit IdentityMapping(uno::Environment aEnv);
+};
+
+}
+
+extern "C"
+{
+
+static void s_free(uno_Mapping * pMapping)
+{
+ delete static_cast<IdentityMapping *>(pMapping);
+}
+
+static void s_acquire(uno_Mapping * pMapping)
+{
+ static OUString s_purpose;
+
+ if (1 == osl_atomic_increment(&static_cast<IdentityMapping *>(pMapping)->m_nRef))
+ {
+ uno_registerMapping(
+ &pMapping,
+ s_free,
+ static_cast<IdentityMapping *>(pMapping)->m_env.get(),
+ static_cast<IdentityMapping *>(pMapping)->m_env.get(),
+ s_purpose.pData);
+ }
+}
+
+static void s_release(uno_Mapping * pMapping)
+{
+ if (!osl_atomic_decrement(&static_cast<IdentityMapping *>(pMapping )->m_nRef))
+ uno_revokeMapping(pMapping);
+}
+
+static void s_mapInterface(uno_Mapping * pMapping,
+ void ** ppOut,
+ void * pInterface,
+ SAL_UNUSED_PARAMETER typelib_InterfaceTypeDescription * /*pInterfaceTypeDescr*/)
+{
+ *ppOut = pInterface;
+
+ if (pInterface)
+ {
+ IdentityMapping * that = static_cast<IdentityMapping *>(pMapping);
+
+ (that->m_env.get()->pExtEnv->acquireInterface)(that->m_env.get()->pExtEnv, pInterface);
+ }
+}
+}
+
+
+IdentityMapping::IdentityMapping(uno::Environment aEnv)
+ : m_nRef(0),
+ m_env(std::move(aEnv))
+{
+ uno_Mapping::acquire = s_acquire;
+ uno_Mapping::release = s_release;
+ uno_Mapping::mapInterface = s_mapInterface;
+}
+
+
+uno_Mapping * createIdentityMapping(uno::Environment const & rEnv)
+{
+ return new IdentityMapping(rEnv);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/IdentityMapping.hxx b/cppu/source/uno/IdentityMapping.hxx
new file mode 100644
index 000000000..8ba081b00
--- /dev/null
+++ b/cppu/source/uno/IdentityMapping.hxx
@@ -0,0 +1,31 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <uno/mapping.h>
+
+namespace com::sun::star::uno
+{
+class Environment;
+}
+
+uno_Mapping* createIdentityMapping(const css::uno::Environment& rEnv);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/any.cxx b/cppu/source/uno/any.cxx
new file mode 100644
index 000000000..e26b97286
--- /dev/null
+++ b/cppu/source/uno/any.cxx
@@ -0,0 +1,142 @@
+/* -*- 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 "copy.hxx"
+#include "destr.hxx"
+
+using namespace cppu;
+
+
+extern "C"
+{
+
+void SAL_CALL uno_type_any_assign(
+ uno_Any * pDest, void * pSource,
+ typelib_TypeDescriptionReference * pType,
+ uno_AcquireFunc acquire, uno_ReleaseFunc release )
+ SAL_THROW_EXTERN_C()
+{
+ _destructAny( pDest, release );
+ if (pType)
+ {
+ _copyConstructAny( pDest, pSource, pType, nullptr, acquire, nullptr );
+ }
+ else
+ {
+ CONSTRUCT_EMPTY_ANY( pDest );
+ }
+}
+
+void SAL_CALL uno_any_assign(
+ uno_Any * pDest, void * pSource,
+ typelib_TypeDescription * pTypeDescr,
+ uno_AcquireFunc acquire, uno_ReleaseFunc release )
+ SAL_THROW_EXTERN_C()
+{
+ _destructAny( pDest, release );
+ if (pTypeDescr)
+ {
+ _copyConstructAny( pDest, pSource, pTypeDescr->pWeakRef, pTypeDescr, acquire, nullptr );
+ }
+ else
+ {
+ CONSTRUCT_EMPTY_ANY( pDest );
+ }
+}
+
+void SAL_CALL uno_type_any_construct(
+ uno_Any * pDest, void * pSource,
+ typelib_TypeDescriptionReference * pType,
+ uno_AcquireFunc acquire )
+ SAL_THROW_EXTERN_C()
+{
+ if (pType)
+ {
+ _copyConstructAny( pDest, pSource, pType, nullptr, acquire, nullptr );
+ }
+ else
+ {
+ CONSTRUCT_EMPTY_ANY( pDest );
+ }
+}
+
+void SAL_CALL uno_any_construct(
+ uno_Any * pDest, void * pSource,
+ typelib_TypeDescription * pTypeDescr,
+ uno_AcquireFunc acquire )
+ SAL_THROW_EXTERN_C()
+{
+ if (pTypeDescr)
+ {
+ _copyConstructAny( pDest, pSource, pTypeDescr->pWeakRef, pTypeDescr, acquire, nullptr );
+ }
+ else
+ {
+ CONSTRUCT_EMPTY_ANY( pDest );
+ }
+}
+
+void SAL_CALL uno_type_any_constructAndConvert(
+ uno_Any * pDest, void * pSource,
+ typelib_TypeDescriptionReference * pType,
+ uno_Mapping * mapping )
+ SAL_THROW_EXTERN_C()
+{
+ if (pType)
+ {
+ _copyConstructAny( pDest, pSource, pType, nullptr, nullptr, mapping );
+ }
+ else
+ {
+ CONSTRUCT_EMPTY_ANY( pDest );
+ }
+}
+
+void SAL_CALL uno_any_constructAndConvert(
+ uno_Any * pDest, void * pSource,
+ typelib_TypeDescription * pTypeDescr,
+ uno_Mapping * mapping )
+ SAL_THROW_EXTERN_C()
+{
+ if (pTypeDescr)
+ {
+ _copyConstructAny( pDest, pSource, pTypeDescr->pWeakRef, pTypeDescr, nullptr, mapping );
+ }
+ else
+ {
+ CONSTRUCT_EMPTY_ANY( pDest );
+ }
+}
+
+void SAL_CALL uno_any_destruct( uno_Any * pValue, uno_ReleaseFunc release )
+ SAL_THROW_EXTERN_C()
+{
+ _destructAny( pValue, release );
+}
+
+void SAL_CALL uno_any_clear( uno_Any * pValue, uno_ReleaseFunc release )
+ SAL_THROW_EXTERN_C()
+{
+ _destructAny( pValue, release );
+ CONSTRUCT_EMPTY_ANY( pValue );
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/assign.hxx b/cppu/source/uno/assign.hxx
new file mode 100644
index 000000000..3e2893fde
--- /dev/null
+++ b/cppu/source/uno/assign.hxx
@@ -0,0 +1,449 @@
+/* -*- 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 .
+ */
+#pragma once
+
+#include "prim.hxx"
+#include "destr.hxx"
+#include "constr.hxx"
+#include "copy.hxx"
+
+
+namespace cppu
+{
+
+
+//#### assignment ##################################################################################
+
+
+inline void _assignInterface(
+ void ** ppDest, void * pSource,
+ uno_AcquireFunc acquire, uno_ReleaseFunc release )
+
+{
+ _acquire( pSource, acquire );
+ void * const pToBeReleased = *ppDest;
+ *ppDest = pSource;
+ _release( pToBeReleased, release );
+}
+
+inline void * _queryInterface(
+ void * pSource,
+ typelib_TypeDescriptionReference * pDestType,
+ uno_QueryInterfaceFunc queryInterface )
+{
+ if (pSource)
+ {
+ if (nullptr == queryInterface)
+ queryInterface = binuno_queryInterface;
+ pSource = (*queryInterface)( pSource, pDestType );
+ }
+ return pSource;
+}
+
+bool assignStruct(
+ void * pDest, void * pSource,
+ typelib_CompoundTypeDescription * pTypeDescr,
+ uno_QueryInterfaceFunc queryInterface, uno_AcquireFunc acquire, uno_ReleaseFunc release );
+
+inline bool _assignStruct(
+ void * pDest, void * pSource,
+ typelib_CompoundTypeDescription * pTypeDescr,
+ uno_QueryInterfaceFunc queryInterface, uno_AcquireFunc acquire, uno_ReleaseFunc release )
+{
+ if (pTypeDescr->pBaseTypeDescription)
+ {
+ // copy base value
+ if (! assignStruct( pDest, pSource, pTypeDescr->pBaseTypeDescription,
+ queryInterface, acquire, release ))
+ {
+ return false;
+ }
+ }
+ // then copy members
+ typelib_TypeDescriptionReference ** ppTypeRefs = pTypeDescr->ppTypeRefs;
+ sal_Int32 * pMemberOffsets = pTypeDescr->pMemberOffsets;
+ sal_Int32 nDescr = pTypeDescr->nMembers;
+ while (nDescr--)
+ {
+ if (! ::uno_type_assignData( static_cast<char *>(pDest) + pMemberOffsets[nDescr],
+ ppTypeRefs[nDescr],
+ static_cast<char *>(pSource) + pMemberOffsets[nDescr],
+ ppTypeRefs[nDescr],
+ queryInterface, acquire, release ))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+inline bool _assignData(
+ void * pDest,
+ typelib_TypeDescriptionReference * pDestType, typelib_TypeDescription * pDestTypeDescr,
+ void * pSource,
+ typelib_TypeDescriptionReference * pSourceType, typelib_TypeDescription * pSourceTypeDescr,
+ uno_QueryInterfaceFunc queryInterface, uno_AcquireFunc acquire, uno_ReleaseFunc release )
+{
+ if (pDest == pSource)
+ return _type_equals( pDestType, pSourceType );
+
+ if (! pSource)
+ {
+ _destructData( pDest, pDestType, pDestTypeDescr, release );
+ _defaultConstructData( pDest, pDestType, pDestTypeDescr );
+ return true;
+ }
+ while (typelib_TypeClass_ANY == pSourceType->eTypeClass)
+ {
+ pSourceTypeDescr = nullptr;
+ pSourceType = static_cast<uno_Any *>(pSource)->pType;
+ pSource = static_cast<uno_Any *>(pSource)->pData;
+ if (pDest == pSource)
+ return true;
+ }
+
+ switch (pDestType->eTypeClass)
+ {
+ case typelib_TypeClass_VOID:
+ return pSourceType->eTypeClass == typelib_TypeClass_VOID;
+ case typelib_TypeClass_CHAR:
+ switch (pSourceType->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ *static_cast<sal_Unicode *>(pDest) = *static_cast<sal_Unicode *>(pSource);
+ return true;
+ default:
+ return false;
+ }
+ case typelib_TypeClass_BOOLEAN:
+ switch (pSourceType->eTypeClass)
+ {
+ case typelib_TypeClass_BOOLEAN:
+ *static_cast<sal_Bool *>(pDest) = bool(*static_cast<sal_Bool *>(pSource));
+ return true;
+ default:
+ return false;
+ }
+ case typelib_TypeClass_BYTE:
+ switch (pSourceType->eTypeClass)
+ {
+ case typelib_TypeClass_BYTE:
+ *static_cast<sal_Int8 *>(pDest) = *static_cast<sal_Int8 *>(pSource);
+ return true;
+ default:
+ return false;
+ }
+ case typelib_TypeClass_SHORT:
+ switch (pSourceType->eTypeClass)
+ {
+ case typelib_TypeClass_BYTE:
+ *static_cast<sal_Int16 *>(pDest) = *static_cast<sal_Int8 *>(pSource);
+ return true;
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ *static_cast<sal_Int16 *>(pDest) = *static_cast<sal_Int16 *>(pSource);
+ return true;
+ default:
+ return false;
+ }
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ switch (pSourceType->eTypeClass)
+ {
+ case typelib_TypeClass_BYTE:
+ *static_cast<sal_uInt16 *>(pDest) = *static_cast<sal_Int8 *>(pSource);
+ return true;
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ *static_cast<sal_uInt16 *>(pDest) = *static_cast<sal_uInt16 *>(pSource);
+ return true;
+ default:
+ return false;
+ }
+ case typelib_TypeClass_LONG:
+ switch (pSourceType->eTypeClass)
+ {
+ case typelib_TypeClass_BYTE:
+ *static_cast<sal_Int32 *>(pDest) = *static_cast<sal_Int8 *>(pSource);
+ return true;
+ case typelib_TypeClass_SHORT:
+ *static_cast<sal_Int32 *>(pDest) = *static_cast<sal_Int16 *>(pSource);
+ return true;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ *static_cast<sal_Int32 *>(pDest) = *static_cast<sal_uInt16 *>(pSource);
+ return true;
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ *static_cast<sal_Int32 *>(pDest) = *static_cast<sal_Int32 *>(pSource);
+ return true;
+ default:
+ return false;
+ }
+ case typelib_TypeClass_UNSIGNED_LONG:
+ switch (pSourceType->eTypeClass)
+ {
+ case typelib_TypeClass_BYTE:
+ *static_cast<sal_uInt32 *>(pDest) = *static_cast<sal_Int8 *>(pSource);
+ return true;
+ case typelib_TypeClass_SHORT:
+ *static_cast<sal_uInt32 *>(pDest) = *static_cast<sal_Int16 *>(pSource);
+ return true;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ *static_cast<sal_uInt32 *>(pDest) = *static_cast<sal_uInt16 *>(pSource);
+ return true;
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ *static_cast<sal_uInt32 *>(pDest) = *static_cast<sal_uInt32 *>(pSource);
+ return true;
+ default:
+ return false;
+ }
+ case typelib_TypeClass_HYPER:
+ switch (pSourceType->eTypeClass)
+ {
+ case typelib_TypeClass_BYTE:
+ *static_cast<sal_Int64 *>(pDest) = *static_cast<sal_Int8 *>(pSource);
+ return true;
+ case typelib_TypeClass_SHORT:
+ *static_cast<sal_Int64 *>(pDest) = *static_cast<sal_Int16 *>(pSource);
+ return true;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ *static_cast<sal_Int64 *>(pDest) = *static_cast<sal_uInt16 *>(pSource);
+ return true;
+ case typelib_TypeClass_LONG:
+ *static_cast<sal_Int64 *>(pDest) = *static_cast<sal_Int32 *>(pSource);
+ return true;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ *static_cast<sal_Int64 *>(pDest) = *static_cast<sal_uInt32 *>(pSource);
+ return true;
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ *static_cast<sal_Int64 *>(pDest) = *static_cast<sal_Int64 *>(pSource);
+ return true;
+ default:
+ return false;
+ }
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ switch (pSourceType->eTypeClass)
+ {
+ case typelib_TypeClass_BYTE:
+ *static_cast<sal_uInt64 *>(pDest) = *static_cast<sal_Int8 *>(pSource);
+ return true;
+ case typelib_TypeClass_SHORT:
+ *static_cast<sal_uInt64 *>(pDest) = *static_cast<sal_Int16 *>(pSource);
+ return true;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ *static_cast<sal_uInt64 *>(pDest) = *static_cast<sal_uInt16 *>(pSource);
+ return true;
+ case typelib_TypeClass_LONG:
+ *static_cast<sal_uInt64 *>(pDest) = *static_cast<sal_Int32 *>(pSource);
+ return true;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ *static_cast<sal_uInt64 *>(pDest) = *static_cast<sal_uInt32 *>(pSource);
+ return true;
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ *static_cast<sal_uInt64 *>(pDest) = *static_cast<sal_uInt64 *>(pSource);
+ return true;
+ default:
+ return false;
+ }
+ case typelib_TypeClass_FLOAT:
+ switch (pSourceType->eTypeClass)
+ {
+ case typelib_TypeClass_BYTE:
+ *static_cast<float *>(pDest) = *static_cast<sal_Int8 *>(pSource);
+ return true;
+ case typelib_TypeClass_SHORT:
+ *static_cast<float *>(pDest) = *static_cast<sal_Int16 *>(pSource);
+ return true;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ *static_cast<float *>(pDest) = *static_cast<sal_uInt16 *>(pSource);
+ return true;
+ case typelib_TypeClass_FLOAT:
+ *static_cast<float *>(pDest) = *static_cast<float *>(pSource);
+ return true;
+ default:
+ return false;
+ }
+ case typelib_TypeClass_DOUBLE:
+ switch (pSourceType->eTypeClass)
+ {
+ case typelib_TypeClass_BYTE:
+ *static_cast<double *>(pDest) = *static_cast<sal_Int8 *>(pSource);
+ return true;
+ case typelib_TypeClass_SHORT:
+ *static_cast<double *>(pDest) = *static_cast<sal_Int16 *>(pSource);
+ return true;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ *static_cast<double *>(pDest) = *static_cast<sal_uInt16 *>(pSource);
+ return true;
+ case typelib_TypeClass_LONG:
+ *static_cast<double *>(pDest) = *static_cast<sal_Int32 *>(pSource);
+ return true;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ *static_cast<double *>(pDest) = *static_cast<sal_uInt32 *>(pSource);
+ return true;
+ case typelib_TypeClass_FLOAT:
+ *static_cast<double *>(pDest) = *static_cast<float *>(pSource);
+ return true;
+ case typelib_TypeClass_DOUBLE:
+ *static_cast<double *>(pDest) = *static_cast<double *>(pSource);
+ return true;
+ default:
+ return false;
+ }
+ case typelib_TypeClass_STRING:
+ switch (pSourceType->eTypeClass)
+ {
+ case typelib_TypeClass_STRING:
+ ::rtl_uString_assign( static_cast<rtl_uString **>(pDest), *static_cast<rtl_uString **>(pSource) );
+ return true;
+ default:
+ return false;
+ }
+ case typelib_TypeClass_TYPE:
+ switch (pSourceType->eTypeClass)
+ {
+ case typelib_TypeClass_TYPE:
+ {
+ typelib_TypeDescriptionReference ** pp = static_cast<typelib_TypeDescriptionReference **>(pDest);
+ ::typelib_typedescriptionreference_release( *pp );
+ *pp = *static_cast<typelib_TypeDescriptionReference **>(pSource);
+ TYPE_ACQUIRE( *pp );
+ return true;
+ }
+ default:
+ return false;
+ }
+ case typelib_TypeClass_ANY:
+ _destructAny( static_cast<uno_Any *>(pDest), release );
+ _copyConstructAny( static_cast<uno_Any *>(pDest), pSource, pSourceType, pSourceTypeDescr, acquire, nullptr );
+ return true;
+ case typelib_TypeClass_ENUM:
+ if (_type_equals( pDestType, pSourceType ))
+ {
+ *static_cast<sal_Int32 *>(pDest) = *static_cast<sal_Int32 *>(pSource);
+ return true;
+ }
+ return false;
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ if (typelib_TypeClass_STRUCT == pSourceType->eTypeClass ||
+ typelib_TypeClass_EXCEPTION == pSourceType->eTypeClass)
+ {
+ bool bRet = false;
+ if (pSourceTypeDescr)
+ {
+ typelib_CompoundTypeDescription * pTypeDescr =
+ reinterpret_cast<typelib_CompoundTypeDescription *>(pSourceTypeDescr);
+ while (pTypeDescr &&
+ !_type_equals(pTypeDescr->aBase.pWeakRef, pDestType))
+ {
+ pTypeDescr = pTypeDescr->pBaseTypeDescription;
+ }
+ if (pTypeDescr)
+ {
+ bRet = _assignStruct(
+ pDest, pSource, pTypeDescr, queryInterface, acquire, release );
+ }
+ }
+ else
+ {
+ TYPELIB_DANGER_GET( &pSourceTypeDescr, pSourceType );
+ typelib_CompoundTypeDescription * pTypeDescr =
+ reinterpret_cast<typelib_CompoundTypeDescription *>(pSourceTypeDescr);
+ while (pTypeDescr &&
+ !_type_equals(pTypeDescr->aBase.pWeakRef, pDestType))
+ {
+ pTypeDescr = pTypeDescr->pBaseTypeDescription;
+ }
+ if (pTypeDescr)
+ {
+ bRet = _assignStruct(
+ pDest, pSource, pTypeDescr, queryInterface, acquire, release );
+ }
+ TYPELIB_DANGER_RELEASE( pSourceTypeDescr );
+ }
+ return bRet;
+ }
+ return false;
+ case typelib_TypeClass_SEQUENCE:
+ if (!_type_equals( pDestType, pSourceType ))
+ return false;
+ // check self assignment (only after _type_equals, to account for shared static empty):
+ if (*static_cast<uno_Sequence **>(pSource) != *static_cast<uno_Sequence **>(pDest))
+ {
+ osl_atomic_increment( &(*static_cast<uno_Sequence **>(pSource))->nRefCount );
+ idestructSequence(
+ *static_cast<uno_Sequence **>(pDest), pDestType, pDestTypeDescr, release );
+ *static_cast<uno_Sequence **>(pDest) = *static_cast<uno_Sequence **>(pSource);
+ }
+ return true;
+ case typelib_TypeClass_INTERFACE:
+ if (typelib_TypeClass_INTERFACE != pSourceType->eTypeClass)
+ return false;
+ if (_type_equals( pDestType, pSourceType ))
+ {
+ _assignInterface( static_cast<void **>(pDest), *static_cast<void **>(pSource), acquire, release );
+ return true;
+ }
+ else if (*static_cast< void ** >(pSource) == nullptr)
+ {
+ // A null reference of any interface type can be converted to a null
+ // reference of any other interface type:
+ void * const pToBeReleased = *static_cast< void ** >(pDest);
+ *static_cast< void ** >(pDest) = nullptr;
+ _release( pToBeReleased, release );
+ return true;
+ }
+ else
+ {
+ if (pSourceTypeDescr)
+ {
+ typelib_TypeDescription * pTD = pSourceTypeDescr;
+ while (pTD && !_type_equals( pTD->pWeakRef, pDestType ))
+ {
+ pTD = &reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD)->pBaseTypeDescription->aBase;
+ }
+ if (pTD) // is base of dest
+ {
+ _assignInterface( static_cast<void **>(pDest), *static_cast<void **>(pSource), acquire, release );
+ return true;
+ }
+ }
+
+ // query for interface:
+ void * pQueried = _queryInterface( *static_cast<void **>(pSource),
+ pDestType, queryInterface );
+ if (pQueried != nullptr) {
+ void * const pToBeReleased = *static_cast<void **>(pDest);
+ *static_cast<void **>(pDest) = pQueried;
+ _release( pToBeReleased, release );
+ }
+ return (pQueried != nullptr);
+ }
+ default:
+ OSL_ASSERT(false);
+ return false;
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/cascade_mapping.cxx b/cppu/source/uno/cascade_mapping.cxx
new file mode 100644
index 000000000..f03d88e52
--- /dev/null
+++ b/cppu/source/uno/cascade_mapping.cxx
@@ -0,0 +1,308 @@
+/* -*- 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/interlck.h>
+#include <rtl/ustring.hxx>
+#include <uno/environment.hxx>
+#include <uno/lbnames.h>
+#include <uno/mapping.hxx>
+#include <uno/dispatcher.h>
+#include <o3tl/string_view.hxx>
+
+#include <cppu/EnvDcp.hxx>
+
+#include "cascade_mapping.hxx"
+
+using namespace com::sun::star;
+
+namespace {
+
+class MediatorMapping : public uno_Mapping
+{
+ oslInterlockedCount m_refCount;
+
+ uno::Mapping m_from2uno;
+ uno::Mapping m_uno2to;
+
+ uno::Environment m_from;
+ uno::Environment m_interm;
+ uno::Environment m_to;
+
+public:
+ void acquire();
+ void release();
+
+ void mapInterface(void ** ppOut,
+ void * pInterface,
+ typelib_InterfaceTypeDescription * pInterfaceTypeDescr);
+ MediatorMapping(uno_Environment * pFrom,
+ uno_Environment * pInterm,
+ uno_Environment * pTo);
+};
+
+}
+
+extern "C" {
+static void s_acquire(uno_Mapping * mapping)
+{
+ MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping);
+ pMediatorMapping->acquire();
+}
+
+static void s_release(uno_Mapping * mapping)
+{
+ MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping);
+ pMediatorMapping->release();
+}
+
+static void s_mapInterface(
+ uno_Mapping * mapping,
+ void ** ppOut,
+ void * pInterface,
+ typelib_InterfaceTypeDescription * pInterfaceTypeDescr)
+{
+ MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping);
+ pMediatorMapping->mapInterface(ppOut, pInterface, pInterfaceTypeDescr);
+}
+}
+
+MediatorMapping::MediatorMapping(uno_Environment * pFrom,
+ uno_Environment * pInterm,
+ uno_Environment * pTo)
+ : m_refCount(0),
+ m_from2uno(pFrom, pInterm),
+ m_uno2to (pInterm, pTo),
+ m_from (pFrom),
+ m_interm (pInterm),
+ m_to (pTo)
+{
+ if (!m_from2uno.get() || !m_uno2to.get())
+ abort();
+
+ uno_Mapping::acquire = s_acquire;
+ uno_Mapping::release = s_release;
+ uno_Mapping::mapInterface = s_mapInterface;
+}
+
+void MediatorMapping::acquire()
+{
+ osl_atomic_increment(&m_refCount);
+}
+
+void MediatorMapping::release()
+{
+ if (osl_atomic_decrement(&m_refCount) == 0)
+ {
+ ::uno_revokeMapping(this);
+ }
+}
+
+extern "C" { static void s_mapInterface_v(va_list * pParam)
+{
+ void ** ppOut = va_arg(*pParam, void **);
+ void * pInterface = va_arg(*pParam, void *);
+ typelib_InterfaceTypeDescription * pInterfaceTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *);
+ uno_Mapping * pMapping = va_arg(*pParam, uno_Mapping *);
+
+ pMapping->mapInterface(pMapping, ppOut, pInterface, pInterfaceTypeDescr);
+}}
+
+void MediatorMapping::mapInterface(
+ void ** ppOut,
+ void * pInterface,
+ typelib_InterfaceTypeDescription * pInterfaceTypeDescr)
+{
+ if (*ppOut != nullptr)
+ {
+ uno_ExtEnvironment * env = m_to.get()->pExtEnv;
+ OSL_ASSERT( env != nullptr );
+ env->releaseInterface( env, *ppOut );
+ *ppOut = nullptr;
+ }
+
+ void * ret = nullptr;
+ uno_Interface * pUnoI = nullptr;
+
+ m_from.invoke(s_mapInterface_v, &pUnoI, pInterface, pInterfaceTypeDescr, m_from2uno.get());
+
+ m_uno2to.mapInterface(&ret, pUnoI, pInterfaceTypeDescr);
+
+ if (pUnoI)
+ m_interm.get()->pExtEnv->releaseInterface(m_interm.get()->pExtEnv, pUnoI);
+
+ *ppOut = ret;
+}
+
+extern "C" { static void s_MediatorMapping_free(uno_Mapping * pMapping)
+ SAL_THROW_EXTERN_C()
+{
+ delete static_cast<MediatorMapping *>(pMapping);
+}}
+
+
+static OUString getPrefix(std::u16string_view str1, std::u16string_view str2)
+{
+ sal_Int32 nIndex1 = 0;
+ sal_Int32 nIndex2 = 0;
+ sal_Int32 sim = 0;
+
+ std::u16string_view token1;
+ std::u16string_view token2;
+
+ do
+ {
+ token1 = o3tl::getToken(str1, 0, ':', nIndex1);
+ token2 = o3tl::getToken(str2, 0, ':', nIndex2);
+
+ if (token1 == token2)
+ sim += token1.size() + 1;
+ }
+ while(nIndex1 == nIndex2 && nIndex1 >= 0 && token1 == token2);
+
+ OUString result;
+
+ if (sim)
+ result = str1.substr(0, sim - 1);
+
+ return result;
+}
+
+// OUString str1("abc:def:ghi");
+// OUString str2("abc:def");
+// OUString str3("abc");
+// OUString str4("");
+
+// OUString pref;
+
+// pref = getPrefix(str1, str1);
+// pref = getPrefix(str1, str2);
+// pref = getPrefix(str1, str3);
+// pref = getPrefix(str1, str4);
+
+// pref = getPrefix(str2, str1);
+// pref = getPrefix(str3, str1);
+// pref = getPrefix(str4, str1);
+
+
+void getCascadeMapping(uno_Mapping ** ppMapping,
+ uno_Environment * pFrom,
+ uno_Environment * pTo,
+ rtl_uString * pAddPurpose)
+{
+ if (pAddPurpose && pAddPurpose->length)
+ return;
+
+ OUString uno_envType(UNO_LB_UNO);
+
+ OUString from_envType = cppu::EnvDcp::getTypeName(pFrom->pTypeName);
+ OUString to_envType = cppu::EnvDcp::getTypeName(pTo->pTypeName);
+ OUString from_envPurpose = cppu::EnvDcp::getPurpose(pFrom->pTypeName);
+ OUString to_envPurpose = cppu::EnvDcp::getPurpose(pTo->pTypeName);
+
+#ifdef LOG_CALLING_named_purpose_getMapping
+ OString s_from_name = OUStringToOString(pFrom->pTypeName, RTL_TEXTENCODING_ASCII_US);
+ OString s_to_name = OUStringToOString(pTo->pTypeName, RTL_TEXTENCODING_ASCII_US);
+
+ std::cerr << __FUNCTION__ << " - creating mediation ";
+ std::cerr << "pFrom: " << s_from_name.getStr();
+ std::cerr <<" pTo: " << s_to_name.getStr() << std::endl;
+#endif
+
+ if (from_envPurpose == to_envPurpose) // gcc:bla => uno:bla
+ return;
+
+ // reaching this point means, we need a mediated mapping!!!
+ // we generally mediate via uno[:free]
+ uno_Environment * pInterm = nullptr;
+
+ // chained uno -> uno
+ if (from_envType == uno_envType && to_envType == uno_envType)
+ {
+ OUString purpose = getPrefix(from_envPurpose, to_envPurpose);
+
+ OUString uno_envDcp = uno_envType + purpose;
+
+ // direct mapping possible?
+ // uno:bla-->uno:bla:blubb
+ if (from_envPurpose == purpose)
+ {
+ OUString rest = to_envPurpose.copy(purpose.getLength());
+
+ sal_Int32 index = rest.indexOf(':', 1);
+ if (index == -1)
+ {
+ uno_getMapping(ppMapping, pFrom, pTo, rest.copy(1).pData);
+ return;
+ }
+
+ uno_envDcp += rest.subView(0, index);
+ }
+ else if (to_envPurpose == purpose)
+ {
+ OUString rest = from_envPurpose.copy(purpose.getLength());
+
+ sal_Int32 index = rest.indexOf(':', 1);
+ if (index == -1)
+ {
+ uno_getMapping(ppMapping, pFrom, pTo, rest.copy(1).pData);
+ return;
+ }
+
+ uno_envDcp += rest.subView(0, index);
+ }
+
+ uno_getEnvironment(&pInterm, uno_envDcp.pData, nullptr);
+ }
+ else if (from_envType != uno_envType && to_envType == uno_envType) // <ANY> -> UNO ?
+ // mediate via uno:purpose(fromEnv)
+ {
+ OUString envDcp = uno_envType + from_envPurpose;
+ uno_getEnvironment(&pInterm, envDcp.pData, nullptr);
+ }
+ else if (from_envType == uno_envType && to_envType != uno_envType) // UNO -> <ANY>?
+ // mediate via uno(context)
+ {
+ OUString envDcp = uno_envType + to_envPurpose;
+ uno_getEnvironment(&pInterm, envDcp.pData, nullptr);
+ }
+ else // everything else
+ // mediate via uno:purpose
+ {
+ OUString purpose = getPrefix(from_envPurpose, to_envPurpose);
+
+ OUString uno_envDcp = uno_envType + purpose;
+
+ uno_getEnvironment(&pInterm, uno_envDcp.pData, nullptr);
+ }
+
+ uno_Mapping * pMapping = new MediatorMapping(pFrom, pInterm, pTo);
+ pInterm->release(pInterm);
+
+
+ pMapping->acquire(pMapping);
+
+ ::uno_registerMapping(&pMapping, s_MediatorMapping_free, pFrom, pTo, pAddPurpose);
+
+ if (*ppMapping)
+ (*ppMapping)->release(*ppMapping);
+
+ *ppMapping = pMapping;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/cascade_mapping.hxx b/cppu/source/uno/cascade_mapping.hxx
new file mode 100644
index 000000000..438143f6b
--- /dev/null
+++ b/cppu/source/uno/cascade_mapping.hxx
@@ -0,0 +1,32 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <uno/environment.h>
+#include <uno/mapping.h>
+#include <rtl/ustring.h>
+
+
+void getCascadeMapping(uno_Mapping ** ppMapping,
+ uno_Environment * pFrom,
+ uno_Environment * pTo,
+ rtl_uString * pAddPurpose );
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/check.cxx b/cppu/source/uno/check.cxx
new file mode 100644
index 000000000..561434aa5
--- /dev/null
+++ b/cppu/source/uno/check.cxx
@@ -0,0 +1,335 @@
+/* -*- 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 <cassert>
+
+#include <cppu/macros.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+#include <uno/any2.h>
+
+
+namespace {
+
+#if defined( _WIN32)
+#pragma pack(push, 8)
+#endif
+
+struct C1
+{
+ sal_Int16 n1;
+};
+struct C2 : public C1
+{
+ sal_Int32 n2 CPPU_GCC3_ALIGN( C1 );
+};
+struct C3 : public C2
+{
+ double d3;
+ sal_Int32 n3;
+};
+struct C4 : public C3
+{
+ sal_Int32 n4 CPPU_GCC3_ALIGN( C3 );
+ double d4;
+};
+struct C5 : public C4
+{
+ sal_Int64 n5;
+ sal_Bool b5;
+};
+struct C6 : public C1
+{
+ C5 c6 CPPU_GCC3_ALIGN( C1 );
+ sal_Bool b6;
+};
+
+struct D
+{
+ sal_Int16 d;
+ sal_Int32 e;
+};
+struct E
+{
+ // [-loplugin:fakebool] false positive:
+ sal_Bool a;
+ // [-loplugin:fakebool] false positive:
+ sal_Bool b;
+ // [-loplugin:fakebool] false positive:
+ sal_Bool c;
+ sal_Int16 d;
+ sal_Int32 e;
+};
+
+struct M
+{
+ sal_Int32 n;
+ sal_Int16 o;
+};
+
+struct N : public M
+{
+ sal_Int16 p CPPU_GCC3_ALIGN( M );
+};
+struct N2
+{
+ M m;
+ sal_Int16 p;
+};
+
+struct O : public M
+{
+ double p;
+ sal_Int16 q;
+};
+struct O2 : public O
+{
+ sal_Int16 p2 CPPU_GCC3_ALIGN( O );
+};
+
+struct P : public N
+{
+ double p2;
+};
+
+struct empty
+{
+};
+struct second : public empty
+{
+ int a;
+};
+
+struct AlignSize_Impl
+{
+ sal_Int16 nInt16;
+ double dDouble;
+};
+
+struct Char1
+{
+ char c1;
+};
+struct Char2 : public Char1
+{
+ char c2 CPPU_GCC3_ALIGN( Char1 );
+};
+struct Char3 : public Char2
+{
+ char c3 CPPU_GCC3_ALIGN( Char2 );
+};
+enum Enum
+{
+ v = SAL_MAX_ENUM
+};
+
+#ifdef _WIN32
+# pragma pack(pop)
+#endif
+
+// [-loplugin:fakebool] false positive:
+static_assert( static_cast<sal_Bool>(true) == sal_True,
+ "must be binary compatible" );
+// [-loplugin:fakebool] false positive:
+static_assert( static_cast<sal_Bool>(false) == sal_False,
+ "must be binary compatible" );
+#if SAL_TYPES_ALIGNMENT8 == 2
+static_assert(offsetof(AlignSize_Impl, dDouble) == 2, "offsetof(AlignSize_Impl, dDouble) != 2");
+static_assert(sizeof(AlignSize_Impl) == 10, "sizeof(AlignSize_Impl) != 10");
+#elif SAL_TYPES_ALIGNMENT8 == 4
+static_assert(offsetof(AlignSize_Impl, dDouble) == 4, "offsetof(AlignSize_Impl, dDouble) != 4");
+static_assert(sizeof(AlignSize_Impl) == 12, "sizeof(AlignSize_Impl) != 12");
+#elif SAL_TYPES_ALIGNMENT8 == 8
+static_assert(offsetof(AlignSize_Impl, dDouble) == 8, "offsetof(AlignSize_Impl, dDouble) != 8");
+static_assert(sizeof(AlignSize_Impl) == 16, "sizeof(AlignSize_Impl) != 16");
+#else
+# error unexpected alignment of 8 byte types
+#endif
+
+// sequence
+static_assert((SAL_SEQUENCE_HEADER_SIZE % 8) == 0, "binary compatibility test failed: (SAL_SEQUENCE_HEADER_SIZE % 8) == 0!!!");
+// enum
+static_assert(sizeof(Enum) == sizeof(sal_Int32), "binary compatibility test failed: (sizeof(Enum) == sizeof(sal_Int32))");
+// any
+static_assert(sizeof(void *) >= sizeof(sal_Int32), "binary compatibility test failed: (sizeof(void *) >= sizeof(sal_Int32))");
+static_assert(sizeof(uno_Any) == sizeof(void *) * 3, "binary compatibility test failed: (sizeof(uno_Any) == sizeof(void *) * 3");
+static_assert(offsetof(uno_Any, pType) == 0, "offsetof(uno_Any, pType) != 0");
+static_assert(offsetof(uno_Any, pData) == 1 * sizeof(void *), "offsetof(uno_Any, pTData) != (1 * sizeof(void *))");
+static_assert(offsetof(uno_Any, pReserved) == 2 * sizeof(void *), "offsetof(uno_Any, pReserved) != (2 * sizeof(void *))");
+// string
+static_assert(sizeof(OUString) == sizeof(rtl_uString *), "binary compatibility test failed: sizeof(OUString) != sizeof(rtl_uString *)");
+// struct
+#if SAL_TYPES_ALIGNMENT8 == 2
+static_assert(sizeof(M) == 6, "sizeof(M) != 6");
+static_assert(sizeof(N) == 8, "sizeof(N) != 8");
+static_assert(sizeof(N2) == 8, "sizeof(N2) != 8");
+static_assert(offsetof(N2, p) == 6, "offsetof(N2, p) != 6");
+#else
+static_assert(sizeof(M) == 8, "sizeof(M) != 8");
+static_assert(sizeof(N) == 12, "sizeof(N) != 12");
+static_assert(sizeof(N2) == 12, "sizeof(N2) != 12");
+static_assert(offsetof(N2, p) == 8, "offsetof(N2, p) != 8");
+#endif
+static_assert(offsetof(M, o) == 4, "offsetof(M, o) != 4");
+
+#if SAL_TYPES_ALIGNMENT8 == 2
+static_assert(sizeof(O) == 16, "sizeof(O) != 16");
+#elif SAL_TYPES_ALIGNMENT8 == 4
+static_assert(sizeof(O) == 20, "sizeof(O) != 20");
+#elif SAL_TYPES_ALIGNMENT8 == 8
+static_assert(sizeof(O) == 24, "sizeof(O) != 24");
+#else
+# error unexpected alignment of 8 byte types
+#endif
+
+#if SAL_TYPES_ALIGNMENT8 == 2
+static_assert(sizeof(C2) == 6, "sizeof(C2) != 6");
+static_assert(sizeof(D) == 6, "sizeof(D) != 6");
+static_assert(offsetof(D, e) == 2, "offsetof(D, e) != 2");
+static_assert(offsetof(E, e) == 6, "offsetof(E, e) != 6");
+#else
+static_assert(sizeof(C2) == 8, "sizeof(C2) != 8");
+static_assert(sizeof(D) == 8, "sizeof(D) != 8");
+static_assert(offsetof(D, e) == 4, "offsetof(D, e) != 4");
+static_assert(offsetof(E, e) == 8, "offsetof(E, e) != 8");
+#endif
+
+static_assert(sizeof(C1) == 2, "sizeof(C1) != 2");
+static_assert(offsetof(E, d) == 4, "offsetof(E, d) != 4");
+
+#if SAL_TYPES_ALIGNMENT8 == 2
+static_assert(sizeof(C3) == 18, "sizeof(C3) != 18");
+static_assert(sizeof(C4) == 30, "sizeof(C4) != 30");
+static_assert(sizeof(C5) == 40, "sizeof(C5) != 40");
+static_assert(sizeof(C6) == 44, "sizeof(C6) != 44");
+
+static_assert(sizeof(O2) == 18, "sizeof(O2) != 18");
+#elif SAL_TYPES_ALIGNMENT8 == 4
+static_assert(sizeof(C3) == 20, "sizeof(C3) != 20");
+static_assert(sizeof(C4) == 32, "sizeof(C4) != 32");
+static_assert(sizeof(C5) == 44, "sizeof(C5) != 44");
+static_assert(sizeof(C6) == 52, "sizeof(C6) != 52");
+
+static_assert(sizeof(O2) == 24, "sizeof(O2) != 24");
+#elif SAL_TYPES_ALIGNMENT8 == 8
+static_assert(sizeof(C3) == 24, "sizeof(C3) != 24");
+static_assert(sizeof(C4) == 40, "sizeof(C4) != 40");
+static_assert(sizeof(C5) == 56, "sizeof(C5) != 56");
+static_assert(sizeof(C6) == 72, "sizeof(C6) != 72");
+
+static_assert(sizeof(O2) == 32, "sizeof(O2) != 32");
+#else
+# error unexpected alignment of 8 byte types
+#endif
+
+static_assert(sizeof(Char3) == 3, "sizeof(Char3) != 3");
+
+#if SAL_TYPES_ALIGNMENT8 == 2
+// max alignment is 2
+static_assert(sizeof(P) == 16, "sizeof(P) != 16");
+#elif SAL_TYPES_ALIGNMENT8 == 4
+// max alignment is 4
+static_assert(sizeof(P) == 20, "sizeof(P) != 20");
+#elif SAL_TYPES_ALIGNMENT8 == 8
+// alignment of P is 8, because of P[] ...
+static_assert(sizeof(P) == 24, "sizeof(P) != 24");
+static_assert(sizeof(second) == sizeof(int), "sizeof(second) != sizeof(int)");
+#else
+# error unexpected alignment of 8 byte types
+#endif
+
+#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
+
+struct Char4
+{
+#if defined __GNUC__ && (__GNUC__ < 12 || (__GNUC__ == 12 && __GNUC_MINOR__ < 1)) && !defined __clang__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wattributes"
+#endif
+ [[maybe_unused]] Char3 chars;
+#if defined __GNUC__ && (__GNUC__ < 12 || (__GNUC__ == 12 && __GNUC_MINOR__ < 1)) && !defined __clang__
+#pragma GCC diagnostic pop
+#endif
+ char c;
+};
+
+template<typename T1, typename T2> std::size_t OFFSET_OF(T2 T1::* p) {
+ return reinterpret_cast< size_t >(reinterpret_cast<char *>(&(reinterpret_cast<T1 *>(16)->*p)) -16);
+}
+
+class BinaryCompatible_Impl
+{
+public:
+ BinaryCompatible_Impl();
+};
+BinaryCompatible_Impl::BinaryCompatible_Impl()
+{
+ assert(OFFSET_OF(&N::p) == 8);
+
+ assert(OFFSET_OF(&C2::n2) == 4);
+
+#if SAL_TYPES_ALIGNMENT8 == 2
+ assert(OFFSET_OF(&C3::d3) == 6);
+ assert(OFFSET_OF(&C3::n3) == 14);
+ assert(OFFSET_OF(&C4::n4) == 18);
+ assert(OFFSET_OF(&C4::d4) == 22);
+ assert(OFFSET_OF(&C5::n5) == 30);
+ assert(OFFSET_OF(&C5::b5) == 38);
+ assert(OFFSET_OF(&C6::c6) == 2);
+ assert(OFFSET_OF(&C6::b6) == 42);
+
+ assert(OFFSET_OF(&O2::p2) == 16);
+#elif SAL_TYPES_ALIGNMENT8 == 4
+ assert(OFFSET_OF(&C3::d3) == 8);
+ assert(OFFSET_OF(&C3::n3) == 16);
+ assert(OFFSET_OF(&C4::n4) == 20);
+ assert(OFFSET_OF(&C4::d4) == 24);
+ assert(OFFSET_OF(&C5::n5) == 32);
+ assert(OFFSET_OF(&C5::b5) == 40);
+ assert(OFFSET_OF(&C6::c6) == 4);
+ assert(OFFSET_OF(&C6::b6) == 48);
+
+ assert(OFFSET_OF(&O2::p2) == 20);
+#elif SAL_TYPES_ALIGNMENT8 == 8
+ assert(OFFSET_OF(&C3::d3) == 8);
+ assert(OFFSET_OF(&C3::n3) == 16);
+ assert(OFFSET_OF(&C4::n4) == 24);
+ assert(OFFSET_OF(&C4::d4) == 32);
+ assert(OFFSET_OF(&C5::n5) == 40);
+ assert(OFFSET_OF(&C5::b5) == 48);
+ assert(OFFSET_OF(&C6::c6) == 8);
+ assert(OFFSET_OF(&C6::b6) == 64);
+
+ assert(OFFSET_OF(&O2::p2) == 24);
+#else
+# error unexpected alignment of 8 byte types
+#endif
+
+ assert(OFFSET_OF(&Char4::c) == 3);
+}
+
+BinaryCompatible_Impl aTest;
+
+#endif
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/constr.hxx b/cppu/source/uno/constr.hxx
new file mode 100644
index 000000000..9ca2eebf8
--- /dev/null
+++ b/cppu/source/uno/constr.hxx
@@ -0,0 +1,138 @@
+/* -*- 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 .
+ */
+#pragma once
+
+#include "prim.hxx"
+#include <osl/diagnose.h>
+
+namespace cppu
+{
+
+
+//#### construction ################################################################################
+
+
+void defaultConstructStruct(
+ void * pMem,
+ typelib_CompoundTypeDescription * pCompType );
+
+inline void _defaultConstructStruct(
+ void * pMem,
+ typelib_CompoundTypeDescription * pTypeDescr )
+{
+ if (pTypeDescr->pBaseTypeDescription)
+ {
+ defaultConstructStruct( pMem, pTypeDescr->pBaseTypeDescription );
+ }
+
+ typelib_TypeDescriptionReference ** ppTypeRefs = pTypeDescr->ppTypeRefs;
+ sal_Int32 * pMemberOffsets = pTypeDescr->pMemberOffsets;
+ sal_Int32 nDescr = pTypeDescr->nMembers;
+
+ while (nDescr--)
+ {
+ ::uno_type_constructData( static_cast<char *>(pMem) + pMemberOffsets[nDescr], ppTypeRefs[nDescr] );
+ }
+}
+
+
+inline void _defaultConstructData(
+ void * pMem,
+ typelib_TypeDescriptionReference * pType,
+ typelib_TypeDescription * pTypeDescr )
+{
+ switch (pType->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ *static_cast<sal_Unicode *>(pMem) = '\0';
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ *static_cast<sal_Bool *>(pMem) = false;
+ break;
+ case typelib_TypeClass_BYTE:
+ *static_cast<sal_Int8 *>(pMem) = 0;
+ break;
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ *static_cast<sal_Int16 *>(pMem) = 0;
+ break;
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ *static_cast<sal_Int32 *>(pMem) = 0;
+ break;
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ *static_cast<sal_Int64 *>(pMem) = 0;
+ break;
+ case typelib_TypeClass_FLOAT:
+ *static_cast<float *>(pMem) = 0.0;
+ break;
+ case typelib_TypeClass_DOUBLE:
+ *static_cast<double *>(pMem) = 0.0;
+ break;
+ case typelib_TypeClass_STRING:
+ *static_cast<rtl_uString **>(pMem) = nullptr;
+ ::rtl_uString_new( static_cast<rtl_uString **>(pMem) );
+ break;
+ case typelib_TypeClass_TYPE:
+ *static_cast<typelib_TypeDescriptionReference **>(pMem) = _getVoidType();
+ break;
+ case typelib_TypeClass_ANY:
+ CONSTRUCT_EMPTY_ANY( static_cast<uno_Any *>(pMem) );
+ break;
+ case typelib_TypeClass_ENUM:
+ if (pTypeDescr)
+ {
+ *static_cast<sal_Int32 *>(pMem) = reinterpret_cast<typelib_EnumTypeDescription *>(pTypeDescr)->nDefaultEnumValue;
+ }
+ else
+ {
+ TYPELIB_DANGER_GET( &pTypeDescr, pType );
+ *static_cast<sal_Int32 *>(pMem) = reinterpret_cast<typelib_EnumTypeDescription *>(pTypeDescr)->nDefaultEnumValue;
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ }
+ break;
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ if (pTypeDescr)
+ {
+ _defaultConstructStruct( pMem, reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr) );
+ }
+ else
+ {
+ TYPELIB_DANGER_GET( &pTypeDescr, pType );
+ _defaultConstructStruct( pMem, reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr) );
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ }
+ break;
+ case typelib_TypeClass_SEQUENCE:
+ *static_cast<uno_Sequence **>(pMem) = createEmptySequence();
+ break;
+ case typelib_TypeClass_INTERFACE:
+ *static_cast<void **>(pMem) = nullptr; // either cpp or c-uno interface
+ break;
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/copy.hxx b/cppu/source/uno/copy.hxx
new file mode 100644
index 000000000..6a71d413f
--- /dev/null
+++ b/cppu/source/uno/copy.hxx
@@ -0,0 +1,655 @@
+/* -*- 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 .
+ */
+#pragma once
+
+#include "prim.hxx"
+#include "constr.hxx"
+#include <cassert>
+#include <cstddef>
+#include <cstdlib>
+#include <type_traits>
+
+namespace cppu
+{
+
+
+//#### copy construction ###########################################################################
+
+namespace {
+
+// The non-dynamic prefix of sal_Sequence (aka uno_Sequence):
+struct SequencePrefix {
+ sal_Int32 nRefCount;
+ sal_Int32 nElements;
+};
+static_assert(sizeof (SequencePrefix) < sizeof (uno_Sequence));
+static_assert(offsetof(SequencePrefix, nRefCount) == offsetof(uno_Sequence, nRefCount));
+static_assert(
+ std::is_same_v<decltype(SequencePrefix::nRefCount), decltype(uno_Sequence::nRefCount)>);
+static_assert(offsetof(SequencePrefix, nElements) == offsetof(uno_Sequence, nElements));
+static_assert(
+ std::is_same_v<decltype(SequencePrefix::nElements), decltype(uno_Sequence::nElements)>);
+
+}
+
+inline uno_Sequence * allocSeq(
+ sal_Int32 nElementSize, sal_Int32 nElements )
+{
+ OSL_ASSERT( nElements >= 0 && nElementSize >= 0 );
+ uno_Sequence * pSeq = nullptr;
+ sal_uInt32 nSize = calcSeqMemSize( nElementSize, nElements );
+ if (nSize > 0)
+ {
+ pSeq = static_cast<uno_Sequence *>(std::malloc( nSize ));
+ if (pSeq != nullptr)
+ {
+ // header init, going via SequencePrefix to avoid UBSan insufficient-object-size
+ // warnings when `nElements == 0` and thus `nSize < sizeof (uno_Sequence)`:
+ auto const header = reinterpret_cast<SequencePrefix *>(pSeq);
+ header->nRefCount = 1;
+ header->nElements = nElements;
+ }
+ }
+ return pSeq;
+}
+
+
+void copyConstructStruct(
+ void * pDest, void * pSource,
+ typelib_CompoundTypeDescription * pTypeDescr,
+ uno_AcquireFunc acquire, uno_Mapping * mapping );
+
+inline void _copyConstructStruct(
+ void * pDest, void * pSource,
+ typelib_CompoundTypeDescription * pTypeDescr,
+ uno_AcquireFunc acquire, uno_Mapping * mapping )
+{
+ if (pTypeDescr->pBaseTypeDescription)
+ {
+ // copy base value
+ copyConstructStruct( pDest, pSource, pTypeDescr->pBaseTypeDescription, acquire, mapping );
+ }
+
+ // then copy members
+ typelib_TypeDescriptionReference ** ppTypeRefs = pTypeDescr->ppTypeRefs;
+ sal_Int32 * pMemberOffsets = pTypeDescr->pMemberOffsets;
+ sal_Int32 nDescr = pTypeDescr->nMembers;
+
+ if (mapping)
+ {
+ while (nDescr--)
+ {
+ ::uno_type_copyAndConvertData(
+ static_cast<char *>(pDest) + pMemberOffsets[nDescr],
+ static_cast<char *>(pSource) + pMemberOffsets[nDescr],
+ ppTypeRefs[nDescr], mapping );
+ }
+ }
+ else
+ {
+ while (nDescr--)
+ {
+ ::uno_type_copyData(
+ static_cast<char *>(pDest) + pMemberOffsets[nDescr],
+ static_cast<char *>(pSource) + pMemberOffsets[nDescr],
+ ppTypeRefs[nDescr], acquire );
+ }
+ }
+}
+
+
+uno_Sequence * copyConstructSequence(
+ uno_Sequence * pSource,
+ typelib_TypeDescriptionReference * pElementType,
+ uno_AcquireFunc acquire, uno_Mapping * mapping );
+
+
+inline void _copyConstructAnyFromData(
+ uno_Any * pDestAny, void * pSource,
+ typelib_TypeDescriptionReference * pType, typelib_TypeDescription * pTypeDescr,
+ uno_AcquireFunc acquire, uno_Mapping * mapping )
+{
+ TYPE_ACQUIRE( pType );
+ pDestAny->pType = pType;
+
+ switch (pType->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ pDestAny->pData = &pDestAny->pReserved;
+ *static_cast<sal_Unicode *>(pDestAny->pData) = *static_cast<sal_Unicode *>(pSource);
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ pDestAny->pData = &pDestAny->pReserved;
+ *static_cast<sal_Bool *>(pDestAny->pData) = bool(*static_cast<sal_Bool *>(pSource));
+ break;
+ case typelib_TypeClass_BYTE:
+ pDestAny->pData = &pDestAny->pReserved;
+ *static_cast<sal_Int8 *>(pDestAny->pData) = *static_cast<sal_Int8 *>(pSource);
+ break;
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ pDestAny->pData = &pDestAny->pReserved;
+ *static_cast<sal_Int16 *>(pDestAny->pData) = *static_cast<sal_Int16 *>(pSource);
+ break;
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ pDestAny->pData = &pDestAny->pReserved;
+ *static_cast<sal_Int32 *>(pDestAny->pData) = *static_cast<sal_Int32 *>(pSource);
+ break;
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ if (sizeof(void *) >= sizeof(sal_Int64))
+ pDestAny->pData = &pDestAny->pReserved;
+ else
+ pDestAny->pData = std::malloc( sizeof(sal_Int64) );
+ assert(pDestAny->pData);
+ *static_cast<sal_Int64 *>(pDestAny->pData) = *static_cast<sal_Int64 *>(pSource);
+ break;
+ case typelib_TypeClass_FLOAT:
+ if (sizeof(void *) >= sizeof(float))
+ pDestAny->pData = &pDestAny->pReserved;
+ else
+ pDestAny->pData = std::malloc( sizeof(float) );
+ assert(pDestAny->pData);
+ *static_cast<float *>(pDestAny->pData) = *static_cast<float *>(pSource);
+ break;
+ case typelib_TypeClass_DOUBLE:
+ if (sizeof(void *) >= sizeof(double))
+ pDestAny->pData = &pDestAny->pReserved;
+ else
+ pDestAny->pData = std::malloc( sizeof(double) );
+ assert(pDestAny->pData);
+ *static_cast<double *>(pDestAny->pData) = *static_cast<double *>(pSource);
+ break;
+ case typelib_TypeClass_STRING:
+ ::rtl_uString_acquire( *static_cast<rtl_uString **>(pSource) );
+ pDestAny->pData = &pDestAny->pReserved;
+ *static_cast<rtl_uString **>(pDestAny->pData) = *static_cast<rtl_uString **>(pSource);
+ break;
+ case typelib_TypeClass_TYPE:
+ TYPE_ACQUIRE( *static_cast<typelib_TypeDescriptionReference **>(pSource) );
+ pDestAny->pData = &pDestAny->pReserved;
+ *static_cast<typelib_TypeDescriptionReference **>(pDestAny->pData) = *static_cast<typelib_TypeDescriptionReference **>(pSource);
+ break;
+ case typelib_TypeClass_ANY:
+ OSL_FAIL( "### unexpected nested any!" );
+ break;
+ case typelib_TypeClass_ENUM:
+ pDestAny->pData = &pDestAny->pReserved;
+ // enum is forced to 32bit long
+ *static_cast<sal_Int32 *>(pDestAny->pData) = *static_cast<sal_Int32 *>(pSource);
+ break;
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ if (pTypeDescr)
+ {
+ pDestAny->pData = std::malloc( pTypeDescr->nSize );
+ _copyConstructStruct(
+ pDestAny->pData, pSource,
+ reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr),
+ acquire, mapping );
+ }
+ else
+ {
+ TYPELIB_DANGER_GET( &pTypeDescr, pType );
+ pDestAny->pData = std::malloc( pTypeDescr->nSize );
+ _copyConstructStruct(
+ pDestAny->pData, pSource,
+ reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr),
+ acquire, mapping );
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ }
+ break;
+ case typelib_TypeClass_SEQUENCE:
+ pDestAny->pData = &pDestAny->pReserved;
+ if (pTypeDescr)
+ {
+ *static_cast<uno_Sequence **>(pDestAny->pData) = copyConstructSequence(
+ *static_cast<uno_Sequence **>(pSource),
+ reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType,
+ acquire, mapping );
+ }
+ else
+ {
+ TYPELIB_DANGER_GET( &pTypeDescr, pType );
+ *static_cast<uno_Sequence **>(pDestAny->pData) = copyConstructSequence(
+ *static_cast<uno_Sequence **>(pSource),
+ reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType,
+ acquire, mapping );
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ }
+ break;
+ case typelib_TypeClass_INTERFACE:
+ pDestAny->pData = &pDestAny->pReserved;
+ if (mapping)
+ {
+ pDestAny->pReserved = _map( *static_cast<void **>(pSource), pType, pTypeDescr, mapping );
+ }
+ else
+ {
+ pDestAny->pReserved = *static_cast<void **>(pSource);
+ _acquire( pDestAny->pReserved, acquire );
+ }
+ break;
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
+}
+
+inline void _copyConstructAny(
+ uno_Any * pDestAny, void * pSource,
+ typelib_TypeDescriptionReference * pType, typelib_TypeDescription * pTypeDescr,
+ uno_AcquireFunc acquire, uno_Mapping * mapping )
+{
+ if (typelib_TypeClass_VOID == pType->eTypeClass)
+ {
+ CONSTRUCT_EMPTY_ANY( pDestAny );
+ }
+ else
+ {
+ if (typelib_TypeClass_ANY == pType->eTypeClass)
+ {
+ if (pSource)
+ {
+ pType = static_cast<uno_Any *>(pSource)->pType;
+ if (typelib_TypeClass_VOID == pType->eTypeClass)
+ {
+ CONSTRUCT_EMPTY_ANY( pDestAny );
+ return;
+ }
+ pTypeDescr = nullptr;
+ pSource = static_cast<uno_Any *>(pSource)->pData;
+ }
+ else
+ {
+ CONSTRUCT_EMPTY_ANY( pDestAny );
+ return;
+ }
+ }
+ if (pSource)
+ {
+ _copyConstructAnyFromData( pDestAny, pSource, pType, pTypeDescr, acquire, mapping );
+ }
+ else // default construct
+ {
+ TYPE_ACQUIRE( pType );
+ pDestAny->pType = pType;
+ switch (pType->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ pDestAny->pData = &pDestAny->pReserved;
+ *static_cast<sal_Unicode *>(pDestAny->pData) = '\0';
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ pDestAny->pData = &pDestAny->pReserved;
+ *static_cast<sal_Bool *>(pDestAny->pData) = false;
+ break;
+ case typelib_TypeClass_BYTE:
+ pDestAny->pData = &pDestAny->pReserved;
+ *static_cast<sal_Int8 *>(pDestAny->pData) = 0;
+ break;
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ pDestAny->pData = &pDestAny->pReserved;
+ *static_cast<sal_Int16 *>(pDestAny->pData) = 0;
+ break;
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ pDestAny->pData = &pDestAny->pReserved;
+ *static_cast<sal_Int32 *>(pDestAny->pData) = 0;
+ break;
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ if (sizeof(void *) >= sizeof(sal_Int64))
+ pDestAny->pData = &pDestAny->pReserved;
+ else
+ pDestAny->pData = std::malloc( sizeof(sal_Int64) );
+ assert(pDestAny->pData);
+ *static_cast<sal_Int64 *>(pDestAny->pData) = 0;
+ break;
+ case typelib_TypeClass_FLOAT:
+ if (sizeof(void *) >= sizeof(float))
+ pDestAny->pData = &pDestAny->pReserved;
+ else
+ pDestAny->pData = std::malloc( sizeof(float) );
+ assert(pDestAny->pData);
+ *static_cast<float *>(pDestAny->pData) = 0.0;
+ break;
+ case typelib_TypeClass_DOUBLE:
+ if (sizeof(void *) >= sizeof(double))
+ pDestAny->pData = &pDestAny->pReserved;
+ else
+ pDestAny->pData = std::malloc( sizeof(double) );
+ assert(pDestAny->pData);
+ *static_cast<double *>(pDestAny->pData) = 0.0;
+ break;
+ case typelib_TypeClass_STRING:
+ pDestAny->pData = &pDestAny->pReserved;
+ *static_cast<rtl_uString **>(pDestAny->pData) = nullptr;
+ ::rtl_uString_new( static_cast<rtl_uString **>(pDestAny->pData) );
+ break;
+ case typelib_TypeClass_TYPE:
+ pDestAny->pData = &pDestAny->pReserved;
+ *static_cast<typelib_TypeDescriptionReference **>(pDestAny->pData) = _getVoidType();
+ break;
+ case typelib_TypeClass_ENUM:
+ pDestAny->pData = &pDestAny->pReserved;
+ if (pTypeDescr)
+ {
+ *static_cast<sal_Int32 *>(pDestAny->pData) = reinterpret_cast<typelib_EnumTypeDescription *>(pTypeDescr)->nDefaultEnumValue;
+ }
+ else
+ {
+ TYPELIB_DANGER_GET( &pTypeDescr, pType );
+ *static_cast<sal_Int32 *>(pDestAny->pData) = reinterpret_cast<typelib_EnumTypeDescription *>(pTypeDescr)->nDefaultEnumValue;
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ }
+ break;
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ if (pTypeDescr)
+ {
+ pDestAny->pData = std::malloc( pTypeDescr->nSize );
+ _defaultConstructStruct(
+ pDestAny->pData, reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr) );
+ }
+ else
+ {
+ TYPELIB_DANGER_GET( &pTypeDescr, pType );
+ pDestAny->pData = std::malloc( pTypeDescr->nSize );
+ _defaultConstructStruct(
+ pDestAny->pData, reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr) );
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ }
+ break;
+ case typelib_TypeClass_SEQUENCE:
+ pDestAny->pData = &pDestAny->pReserved;
+ *static_cast<uno_Sequence **>(pDestAny->pData) = createEmptySequence();
+ break;
+ case typelib_TypeClass_INTERFACE:
+ pDestAny->pData = &pDestAny->pReserved;
+ pDestAny->pReserved = nullptr; // either cpp or c-uno interface
+ break;
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
+ }
+ }
+}
+
+inline uno_Sequence * icopyConstructSequence(
+ uno_Sequence * pSource,
+ typelib_TypeDescriptionReference * pElementType,
+ uno_AcquireFunc acquire, uno_Mapping * mapping )
+{
+ typelib_TypeClass eTypeClass = pElementType->eTypeClass;
+ if (!mapping ||
+ (eTypeClass <= typelib_TypeClass_ENUM &&
+ eTypeClass != typelib_TypeClass_ANY))
+ {
+ osl_atomic_increment( &pSource->nRefCount );
+ return pSource;
+ }
+ else // create new sequence
+ {
+ uno_Sequence * pDest;
+ sal_Int32 nElements = pSource->nElements;
+ if (nElements)
+ {
+ switch (eTypeClass)
+ {
+ case typelib_TypeClass_ANY:
+ {
+ pDest = allocSeq( sizeof (uno_Any), nElements );
+ if (pDest != nullptr)
+ {
+ uno_Any * pDestElements = reinterpret_cast<uno_Any *>(pDest->elements);
+ uno_Any * pSourceElements = reinterpret_cast<uno_Any *>(pSource->elements);
+ for ( sal_Int32 nPos = nElements; nPos--; )
+ {
+ typelib_TypeDescriptionReference * pType =
+ pSourceElements[nPos].pType;
+ if (typelib_TypeClass_VOID == pType->eTypeClass)
+ {
+ CONSTRUCT_EMPTY_ANY( &pDestElements[nPos] );
+ }
+ else
+ {
+ _copyConstructAnyFromData(
+ &pDestElements[nPos],
+ pSourceElements[nPos].pData,
+ pType, nullptr,
+ acquire, mapping );
+ }
+ }
+ }
+ break;
+ }
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ typelib_TypeDescription * pElementTypeDescr = nullptr;
+ TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
+ sal_Int32 nElementSize = pElementTypeDescr->nSize;
+ char * pSourceElements = pSource->elements;
+ pDest = allocSeq( nElementSize, nElements );
+ if (pDest != nullptr)
+ {
+ char * pElements = pDest->elements;
+ for ( sal_Int32 nPos = nElements; nPos--; )
+ {
+ _copyConstructStruct(
+ pElements + (nPos * nElementSize),
+ pSourceElements + (nPos * nElementSize),
+ reinterpret_cast<typelib_CompoundTypeDescription *>(
+ pElementTypeDescr),
+ acquire, mapping );
+ }
+ }
+ TYPELIB_DANGER_RELEASE( pElementTypeDescr );
+ break;
+ }
+ case typelib_TypeClass_SEQUENCE: // sequence of sequence
+ {
+ // coverity[suspicious_sizeof] - sizeof(uno_Sequence*) is correct here
+ pDest = allocSeq( sizeof (uno_Sequence *), nElements );
+ if (pDest != nullptr)
+ {
+ typelib_TypeDescription * pElementTypeDescr = nullptr;
+ TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
+ typelib_TypeDescriptionReference * pSeqElementType =
+ reinterpret_cast<typelib_IndirectTypeDescription *>(
+ pElementTypeDescr)->pType;
+
+ uno_Sequence ** pDestElements =
+ reinterpret_cast<uno_Sequence **>(pDest->elements);
+ uno_Sequence ** pSourceElements =
+ reinterpret_cast<uno_Sequence **>(pSource->elements);
+ for ( sal_Int32 nPos = nElements; nPos--; )
+ {
+ uno_Sequence * pNew = copyConstructSequence(
+ pSourceElements[nPos],
+ pSeqElementType,
+ acquire, mapping );
+ OSL_ASSERT( pNew != nullptr );
+ // ought never be a memory allocation problem,
+ // because of reference counted sequence handles
+ pDestElements[ nPos ] = pNew;
+ }
+
+ TYPELIB_DANGER_RELEASE( pElementTypeDescr );
+ }
+ break;
+ }
+ case typelib_TypeClass_INTERFACE:
+ {
+ pDest = allocSeq( sizeof (void *), nElements );
+ if (pDest != nullptr)
+ {
+ char * pElements = pDest->elements;
+ void ** pSourceElements = reinterpret_cast<void **>(pSource->elements);
+ typelib_TypeDescription * pElementTypeDescr = nullptr;
+ TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
+ for ( sal_Int32 nPos = nElements; nPos--; )
+ {
+ reinterpret_cast<void **>(pElements)[nPos] = nullptr;
+ if (pSourceElements[nPos])
+ {
+ (*mapping->mapInterface)(
+ mapping, reinterpret_cast<void **>(pElements) + nPos,
+ pSourceElements[nPos],
+ reinterpret_cast<typelib_InterfaceTypeDescription *>(
+ pElementTypeDescr) );
+ }
+ }
+ TYPELIB_DANGER_RELEASE( pElementTypeDescr );
+ }
+ break;
+ }
+ default:
+ OSL_FAIL( "### unexpected sequence element type!" );
+ pDest = nullptr;
+ break;
+ }
+ }
+ else // empty sequence
+ {
+ pDest = allocSeq( 0, 0 );
+ }
+
+ return pDest;
+ }
+}
+
+
+inline void _copyConstructData(
+ void * pDest, void * pSource,
+ typelib_TypeDescriptionReference * pType, typelib_TypeDescription * pTypeDescr,
+ uno_AcquireFunc acquire, uno_Mapping * mapping )
+{
+ switch (pType->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ *static_cast<sal_Unicode *>(pDest) = *static_cast<sal_Unicode *>(pSource);
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ *static_cast<sal_Bool *>(pDest) = bool(*static_cast<sal_Bool *>(pSource));
+ break;
+ case typelib_TypeClass_BYTE:
+ *static_cast<sal_Int8 *>(pDest) = *static_cast<sal_Int8 *>(pSource);
+ break;
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ *static_cast<sal_Int16 *>(pDest) = *static_cast<sal_Int16 *>(pSource);
+ break;
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ *static_cast<sal_Int32 *>(pDest) = *static_cast<sal_Int32 *>(pSource);
+ break;
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ *static_cast<sal_Int64 *>(pDest) = *static_cast<sal_Int64 *>(pSource);
+ break;
+ case typelib_TypeClass_FLOAT:
+ *static_cast<float *>(pDest) = *static_cast<float *>(pSource);
+ break;
+ case typelib_TypeClass_DOUBLE:
+ *static_cast<double *>(pDest) = *static_cast<double *>(pSource);
+ break;
+ case typelib_TypeClass_STRING:
+ ::rtl_uString_acquire( *static_cast<rtl_uString **>(pSource) );
+ *static_cast<rtl_uString **>(pDest) = *static_cast<rtl_uString **>(pSource);
+ break;
+ case typelib_TypeClass_TYPE:
+ TYPE_ACQUIRE( *static_cast<typelib_TypeDescriptionReference **>(pSource) );
+ *static_cast<typelib_TypeDescriptionReference **>(pDest) = *static_cast<typelib_TypeDescriptionReference **>(pSource);
+ break;
+ case typelib_TypeClass_ANY:
+ _copyConstructAny(
+ static_cast<uno_Any *>(pDest), static_cast<uno_Any *>(pSource)->pData,
+ static_cast<uno_Any *>(pSource)->pType, nullptr,
+ acquire, mapping );
+ break;
+ case typelib_TypeClass_ENUM:
+ *static_cast<sal_Int32 *>(pDest) = *static_cast<sal_Int32 *>(pSource);
+ break;
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ if (pTypeDescr)
+ {
+ _copyConstructStruct(
+ pDest, pSource,
+ reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr),
+ acquire, mapping );
+ }
+ else
+ {
+ TYPELIB_DANGER_GET( &pTypeDescr, pType );
+ _copyConstructStruct(
+ pDest, pSource,
+ reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr),
+ acquire, mapping );
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ }
+ break;
+ case typelib_TypeClass_SEQUENCE:
+ if (mapping)
+ {
+ if (pTypeDescr)
+ {
+ *static_cast<uno_Sequence **>(pDest) = icopyConstructSequence(
+ *static_cast<uno_Sequence **>(pSource),
+ reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType,
+ acquire, mapping );
+ }
+ else
+ {
+ TYPELIB_DANGER_GET( &pTypeDescr, pType );
+ *static_cast<uno_Sequence **>(pDest) = icopyConstructSequence(
+ *static_cast<uno_Sequence **>(pSource),
+ reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType,
+ acquire, mapping );
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ }
+ }
+ else
+ {
+ osl_atomic_increment( &(*static_cast<uno_Sequence **>(pSource))->nRefCount );
+ *static_cast<uno_Sequence **>(pDest) = *static_cast<uno_Sequence **>(pSource);
+ }
+ break;
+ case typelib_TypeClass_INTERFACE:
+ if (mapping)
+ *static_cast<void **>(pDest) = _map( *static_cast<void **>(pSource), pType, pTypeDescr, mapping );
+ else
+ {
+ *static_cast<void **>(pDest) = *static_cast<void **>(pSource);
+ _acquire( *static_cast<void **>(pDest), acquire );
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/data.cxx b/cppu/source/uno/data.cxx
new file mode 100644
index 000000000..339e650fe
--- /dev/null
+++ b/cppu/source/uno/data.cxx
@@ -0,0 +1,316 @@
+/* -*- 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/log.hxx>
+#include <uno/data.h>
+
+#include "constr.hxx"
+#include "destr.hxx"
+#include "copy.hxx"
+#include "assign.hxx"
+#include "eq.hxx"
+
+using namespace ::cppu;
+
+namespace cppu
+{
+
+// Sequence<>() (default ctor) relies on this being static:
+uno_Sequence g_emptySeq = { 1, 0, { 0 } };
+typelib_TypeDescriptionReference * g_pVoidType = nullptr;
+
+
+void * binuno_queryInterface( void * pUnoI, typelib_TypeDescriptionReference * pDestType )
+{
+ // init queryInterface() td
+ static typelib_TypeDescription* g_pQITD = []() {
+ typelib_TypeDescriptionReference* type_XInterface
+ = *typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE);
+ typelib_InterfaceTypeDescription* pTXInterfaceDescr = nullptr;
+ TYPELIB_DANGER_GET(reinterpret_cast<typelib_TypeDescription**>(&pTXInterfaceDescr),
+ type_XInterface);
+ assert(pTXInterfaceDescr->ppAllMembers);
+ typelib_TypeDescription* pQITD = nullptr;
+ typelib_typedescriptionreference_getDescription(&pQITD,
+ pTXInterfaceDescr->ppAllMembers[0]);
+ // coverity[callee_ptr_arith] - not a bug
+ TYPELIB_DANGER_RELEASE(&pTXInterfaceDescr->aBase);
+ return pQITD;
+ }();
+
+ uno_Any aRet, aExc;
+ uno_Any * pExc = &aExc;
+ void * aArgs[ 1 ];
+ aArgs[ 0 ] = &pDestType;
+ (*static_cast<uno_Interface *>(pUnoI)->pDispatcher)(
+ static_cast<uno_Interface *>(pUnoI), g_pQITD, &aRet, aArgs, &pExc );
+
+ uno_Interface * ret = nullptr;
+ if (nullptr == pExc)
+ {
+ typelib_TypeDescriptionReference * ret_type = aRet.pType;
+ switch (ret_type->eTypeClass)
+ {
+ case typelib_TypeClass_VOID: // common case
+ typelib_typedescriptionreference_release( ret_type );
+ break;
+ case typelib_TypeClass_INTERFACE:
+ // tweaky... avoiding acquire/ release pair
+ typelib_typedescriptionreference_release( ret_type );
+ ret = static_cast<uno_Interface *>(aRet.pReserved); // serving acquired interface
+ break;
+ default:
+ _destructAny( &aRet, nullptr );
+ break;
+ }
+ }
+ else
+ {
+ SAL_WARN(
+ "cppu",
+ "exception occurred querying for interface "
+ << OUString(pDestType->pTypeName) << ": ["
+ << OUString(pExc->pType->pTypeName) << "] "
+ << *static_cast<OUString const *>(pExc->pData));
+ // Message is very first member
+ uno_any_destruct( pExc, nullptr );
+ }
+ return ret;
+}
+
+
+void defaultConstructStruct(
+ void * pMem,
+ typelib_CompoundTypeDescription * pCompType )
+{
+ _defaultConstructStruct( pMem, pCompType );
+}
+
+void copyConstructStruct(
+ void * pDest, void * pSource,
+ typelib_CompoundTypeDescription * pTypeDescr,
+ uno_AcquireFunc acquire, uno_Mapping * mapping )
+{
+ _copyConstructStruct( pDest, pSource, pTypeDescr, acquire, mapping );
+}
+
+void destructStruct(
+ void * pValue,
+ typelib_CompoundTypeDescription * pTypeDescr,
+ uno_ReleaseFunc release )
+{
+ _destructStruct( pValue, pTypeDescr, release );
+}
+
+bool equalStruct(
+ void * pDest, void *pSource,
+ typelib_CompoundTypeDescription * pTypeDescr,
+ uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release )
+{
+ return _equalStruct( pDest, pSource, pTypeDescr, queryInterface, release );
+}
+
+bool assignStruct(
+ void * pDest, void * pSource,
+ typelib_CompoundTypeDescription * pTypeDescr,
+ uno_QueryInterfaceFunc queryInterface, uno_AcquireFunc acquire, uno_ReleaseFunc release )
+{
+ return _assignStruct( pDest, pSource, pTypeDescr, queryInterface, acquire, release );
+}
+
+
+uno_Sequence * copyConstructSequence(
+ uno_Sequence * pSource,
+ typelib_TypeDescriptionReference * pElementType,
+ uno_AcquireFunc acquire, uno_Mapping * mapping )
+{
+ return icopyConstructSequence( pSource, pElementType, acquire, mapping );
+}
+
+
+void destructSequence(
+ uno_Sequence * pSequence,
+ typelib_TypeDescriptionReference * pType,
+ typelib_TypeDescription * pTypeDescr,
+ uno_ReleaseFunc release )
+{
+ idestructSequence( pSequence, pType, pTypeDescr, release );
+}
+
+
+bool equalSequence(
+ uno_Sequence * pDest, uno_Sequence * pSource,
+ typelib_TypeDescriptionReference * pElementType,
+ uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release )
+{
+ return _equalSequence( pDest, pSource, pElementType, queryInterface, release );
+}
+
+}
+
+extern "C"
+{
+
+void SAL_CALL uno_type_constructData(
+ void * pMem, typelib_TypeDescriptionReference * pType )
+ SAL_THROW_EXTERN_C()
+{
+ _defaultConstructData( pMem, pType, nullptr );
+}
+
+void SAL_CALL uno_constructData(
+ void * pMem, typelib_TypeDescription * pTypeDescr )
+ SAL_THROW_EXTERN_C()
+{
+ _defaultConstructData( pMem, pTypeDescr->pWeakRef, pTypeDescr );
+}
+
+void SAL_CALL uno_type_destructData(
+ void * pValue, typelib_TypeDescriptionReference * pType,
+ uno_ReleaseFunc release )
+ SAL_THROW_EXTERN_C()
+{
+ _destructData( pValue, pType, nullptr, release );
+}
+
+void SAL_CALL uno_destructData(
+ void * pValue,
+ typelib_TypeDescription * pTypeDescr,
+ uno_ReleaseFunc release )
+ SAL_THROW_EXTERN_C()
+{
+ _destructData( pValue, pTypeDescr->pWeakRef, pTypeDescr, release );
+}
+
+void SAL_CALL uno_type_copyData(
+ void * pDest, void * pSource,
+ typelib_TypeDescriptionReference * pType,
+ uno_AcquireFunc acquire )
+ SAL_THROW_EXTERN_C()
+{
+ _copyConstructData( pDest, pSource, pType, nullptr, acquire, nullptr );
+}
+
+void SAL_CALL uno_copyData(
+ void * pDest, void * pSource,
+ typelib_TypeDescription * pTypeDescr,
+ uno_AcquireFunc acquire )
+ SAL_THROW_EXTERN_C()
+{
+ _copyConstructData( pDest, pSource, pTypeDescr->pWeakRef, pTypeDescr, acquire, nullptr );
+}
+
+void SAL_CALL uno_type_copyAndConvertData(
+ void * pDest, void * pSource,
+ typelib_TypeDescriptionReference * pType,
+ uno_Mapping * mapping )
+ SAL_THROW_EXTERN_C()
+{
+ _copyConstructData( pDest, pSource, pType, nullptr, nullptr, mapping );
+}
+
+void SAL_CALL uno_copyAndConvertData(
+ void * pDest, void * pSource,
+ typelib_TypeDescription * pTypeDescr,
+ uno_Mapping * mapping )
+ SAL_THROW_EXTERN_C()
+{
+ _copyConstructData( pDest, pSource, pTypeDescr->pWeakRef, pTypeDescr, nullptr, mapping );
+}
+
+sal_Bool SAL_CALL uno_type_equalData(
+ void * pVal1, typelib_TypeDescriptionReference * pVal1Type,
+ void * pVal2, typelib_TypeDescriptionReference * pVal2Type,
+ uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release )
+ SAL_THROW_EXTERN_C()
+{
+ return _equalData(
+ pVal1, pVal1Type, nullptr,
+ pVal2, pVal2Type,
+ queryInterface, release );
+}
+
+sal_Bool SAL_CALL uno_equalData(
+ void * pVal1, typelib_TypeDescription * pVal1TD,
+ void * pVal2, typelib_TypeDescription * pVal2TD,
+ uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release )
+ SAL_THROW_EXTERN_C()
+{
+ return _equalData(
+ pVal1, pVal1TD->pWeakRef, pVal1TD,
+ pVal2, pVal2TD->pWeakRef,
+ queryInterface, release );
+}
+
+sal_Bool SAL_CALL uno_type_assignData(
+ void * pDest, typelib_TypeDescriptionReference * pDestType,
+ void * pSource, typelib_TypeDescriptionReference * pSourceType,
+ uno_QueryInterfaceFunc queryInterface, uno_AcquireFunc acquire, uno_ReleaseFunc release )
+ SAL_THROW_EXTERN_C()
+{
+ return _assignData(
+ pDest, pDestType, nullptr,
+ pSource, pSourceType, nullptr,
+ queryInterface, acquire, release );
+}
+
+sal_Bool SAL_CALL uno_assignData(
+ void * pDest, typelib_TypeDescription * pDestTD,
+ void * pSource, typelib_TypeDescription * pSourceTD,
+ uno_QueryInterfaceFunc queryInterface, uno_AcquireFunc acquire, uno_ReleaseFunc release )
+ SAL_THROW_EXTERN_C()
+{
+ return _assignData(
+ pDest, pDestTD->pWeakRef, pDestTD,
+ pSource, pSourceTD->pWeakRef, pSourceTD,
+ queryInterface, acquire, release );
+}
+
+sal_Bool SAL_CALL uno_type_isAssignableFromData(
+ typelib_TypeDescriptionReference * pAssignable,
+ void * pFrom, typelib_TypeDescriptionReference * pFromType,
+ uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release )
+ SAL_THROW_EXTERN_C()
+{
+ if (::typelib_typedescriptionreference_isAssignableFrom( pAssignable, pFromType ))
+ return true;
+ if (typelib_TypeClass_INTERFACE != pFromType->eTypeClass ||
+ typelib_TypeClass_INTERFACE != pAssignable->eTypeClass)
+ {
+ return false;
+ }
+
+ // query
+ if (nullptr == pFrom)
+ return false;
+ void * pInterface = *static_cast<void **>(pFrom);
+ if (nullptr == pInterface)
+ return false;
+
+ if (nullptr == queryInterface)
+ queryInterface = binuno_queryInterface;
+ void * p = (*queryInterface)( pInterface, pAssignable );
+ _release( p, release );
+ return (nullptr != p);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/destr.hxx b/cppu/source/uno/destr.hxx
new file mode 100644
index 000000000..13e4ca044
--- /dev/null
+++ b/cppu/source/uno/destr.hxx
@@ -0,0 +1,352 @@
+/* -*- 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 .
+ */
+#pragma once
+
+#include <sal/config.h>
+#include <osl/diagnose.h>
+
+#include <cassert>
+#include <cstdlib>
+
+#include "prim.hxx"
+
+namespace cppu
+{
+
+
+//#### destruction #################################################################################
+
+
+void destructStruct(
+ void * pValue,
+ typelib_CompoundTypeDescription * pTypeDescr,
+ uno_ReleaseFunc release );
+
+inline void _destructStruct(
+ void * pValue,
+ typelib_CompoundTypeDescription * pTypeDescr,
+ uno_ReleaseFunc release )
+{
+ if (pTypeDescr->pBaseTypeDescription)
+ {
+ destructStruct( pValue, pTypeDescr->pBaseTypeDescription, release );
+ }
+
+ typelib_TypeDescriptionReference ** ppTypeRefs = pTypeDescr->ppTypeRefs;
+ sal_Int32 * pMemberOffsets = pTypeDescr->pMemberOffsets;
+ sal_Int32 nDescr = pTypeDescr->nMembers;
+ while (nDescr--)
+ {
+ ::uno_type_destructData(
+ static_cast<char *>(pValue) + pMemberOffsets[nDescr],
+ ppTypeRefs[nDescr], release );
+ }
+}
+
+
+void destructSequence(
+ uno_Sequence * pSequence,
+ typelib_TypeDescriptionReference * pType,
+ typelib_TypeDescription * pTypeDescr,
+ uno_ReleaseFunc release );
+
+
+inline void _destructAny(
+ uno_Any * pAny,
+ uno_ReleaseFunc release )
+{
+ typelib_TypeDescriptionReference * pType = pAny->pType;
+
+ switch (pType->eTypeClass)
+ {
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ if (sizeof(void *) < sizeof(sal_Int64))
+ {
+ std::free( pAny->pData );
+ }
+ break;
+ case typelib_TypeClass_FLOAT:
+ if (sizeof(void *) < sizeof(float))
+ {
+ std::free( pAny->pData );
+ }
+ break;
+ case typelib_TypeClass_DOUBLE:
+ if (sizeof(void *) < sizeof(double))
+ {
+ std::free( pAny->pData );
+ }
+ break;
+ case typelib_TypeClass_STRING:
+ ::rtl_uString_release( static_cast<rtl_uString *>(pAny->pReserved) );
+ break;
+ case typelib_TypeClass_TYPE:
+ ::typelib_typedescriptionreference_release(
+ static_cast<typelib_TypeDescriptionReference *>(pAny->pReserved) );
+ break;
+ case typelib_TypeClass_ANY:
+ OSL_FAIL( "### unexpected nested any!" );
+ ::uno_any_destruct( static_cast<uno_Any *>(pAny->pData), release );
+ std::free( pAny->pData );
+ break;
+ case typelib_TypeClass_TYPEDEF:
+ OSL_FAIL( "### unexpected typedef!" );
+ break;
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ typelib_TypeDescription * pTypeDescr = nullptr;
+ TYPELIB_DANGER_GET( &pTypeDescr, pType );
+ _destructStruct( pAny->pData, reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr), release );
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ std::free( pAny->pData );
+ break;
+ }
+ case typelib_TypeClass_SEQUENCE:
+ {
+ destructSequence(
+ static_cast<uno_Sequence *>(pAny->pReserved), pType, nullptr, release );
+ break;
+ }
+ case typelib_TypeClass_INTERFACE:
+ _release( pAny->pReserved, release );
+ break;
+ default:
+ break;
+ }
+#if OSL_DEBUG_LEVEL > 0
+ pAny->pData = reinterpret_cast<void *>(uintptr_t(0xdeadbeef));
+#endif
+
+ ::typelib_typedescriptionreference_release( pType );
+}
+
+inline sal_Int32 idestructElements(
+ void * pElements, typelib_TypeDescriptionReference * pElementType,
+ sal_Int32 nStartIndex, sal_Int32 nStopIndex,
+ uno_ReleaseFunc release )
+{
+ switch (pElementType->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ return sal_Int32(sizeof(sal_Unicode));
+ case typelib_TypeClass_BOOLEAN:
+ return sal_Int32(sizeof(sal_Bool));
+ case typelib_TypeClass_BYTE:
+ return sal_Int32(sizeof(sal_Int8));
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ return sal_Int32(sizeof(sal_Int16));
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ return sal_Int32(sizeof(sal_Int32));
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ return sal_Int32(sizeof(sal_Int64));
+ case typelib_TypeClass_FLOAT:
+ return sal_Int32(sizeof(float));
+ case typelib_TypeClass_DOUBLE:
+ return sal_Int32(sizeof(double));
+
+ case typelib_TypeClass_STRING:
+ {
+ rtl_uString ** pDest = static_cast<rtl_uString **>(pElements);
+ for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
+ {
+ ::rtl_uString_release( pDest[nPos] );
+ }
+ return sal_Int32(sizeof(rtl_uString *));
+ }
+ case typelib_TypeClass_TYPE:
+ {
+ typelib_TypeDescriptionReference ** pDest = static_cast<typelib_TypeDescriptionReference **>(pElements);
+ for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
+ {
+ ::typelib_typedescriptionreference_release( pDest[nPos] );
+ }
+ return sal_Int32(sizeof(typelib_TypeDescriptionReference *));
+ }
+ case typelib_TypeClass_ANY:
+ {
+ uno_Any * pDest = static_cast<uno_Any *>(pElements);
+ for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
+ {
+ _destructAny( &pDest[nPos], release );
+ }
+ return sal_Int32(sizeof(uno_Any));
+ }
+ case typelib_TypeClass_ENUM:
+ return sal_Int32(sizeof(sal_Int32));
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ typelib_TypeDescription * pElementTypeDescr = nullptr;
+ TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
+ sal_Int32 nElementSize = pElementTypeDescr->nSize;
+ for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
+ {
+ _destructStruct(
+ static_cast<char *>(pElements) + (nElementSize * nPos),
+ reinterpret_cast<typelib_CompoundTypeDescription *>(pElementTypeDescr),
+ release );
+ }
+ sal_Int32 nSize = pElementTypeDescr->nSize;
+ TYPELIB_DANGER_RELEASE( pElementTypeDescr );
+ return nSize;
+ }
+ case typelib_TypeClass_SEQUENCE:
+ {
+ typelib_TypeDescription * pElementTypeDescr = nullptr;
+ TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
+ uno_Sequence ** pDest = static_cast<uno_Sequence **>(pElements);
+ for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
+ {
+ destructSequence(
+ pDest[nPos],
+ pElementTypeDescr->pWeakRef, pElementTypeDescr,
+ release );
+ }
+ TYPELIB_DANGER_RELEASE( pElementTypeDescr );
+ return sal_Int32(sizeof(uno_Sequence *));
+ }
+ case typelib_TypeClass_INTERFACE:
+ {
+ if (release)
+ {
+ for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
+ {
+ void * p = static_cast<void **>(pElements)[nPos];
+ if (p)
+ {
+ (*release)( p );
+ }
+ }
+ }
+ else
+ {
+ for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
+ {
+ uno_Interface * p = static_cast<uno_Interface **>(pElements)[nPos];
+ if (p)
+ {
+ (*p->release)( p );
+ }
+ }
+ }
+ return sal_Int32(sizeof(void *));
+ }
+ default:
+ OSL_ASSERT(false);
+ return 0;
+ }
+}
+
+inline void idestroySequence(
+ uno_Sequence * pSeq,
+ typelib_TypeDescriptionReference * pType,
+ typelib_TypeDescription * pTypeDescr,
+ uno_ReleaseFunc release )
+{
+ assert(pSeq != nullptr);
+ assert(pSeq->nRefCount == 0);
+ if (pSeq->nElements > 0)
+ {
+ if (pTypeDescr)
+ {
+ idestructElements(
+ pSeq->elements,
+ reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType, 0,
+ pSeq->nElements, release );
+ }
+ else
+ {
+ TYPELIB_DANGER_GET( &pTypeDescr, pType );
+ idestructElements(
+ pSeq->elements,
+ reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType, 0,
+ pSeq->nElements, release );
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ }
+ }
+ std::free( pSeq );
+}
+
+inline void idestructSequence(
+ uno_Sequence * pSeq,
+ typelib_TypeDescriptionReference * pType,
+ typelib_TypeDescription * pTypeDescr,
+ uno_ReleaseFunc release )
+{
+ if (osl_atomic_decrement( &pSeq->nRefCount ) == 0)
+ {
+ idestroySequence(pSeq, pType, pTypeDescr, release);
+ }
+}
+
+inline void _destructData(
+ void * pValue,
+ typelib_TypeDescriptionReference * pType,
+ typelib_TypeDescription * pTypeDescr,
+ uno_ReleaseFunc release )
+{
+ switch (pType->eTypeClass)
+ {
+ case typelib_TypeClass_STRING:
+ ::rtl_uString_release( *static_cast<rtl_uString **>(pValue) );
+ break;
+ case typelib_TypeClass_TYPE:
+ ::typelib_typedescriptionreference_release( *static_cast<typelib_TypeDescriptionReference **>(pValue) );
+ break;
+ case typelib_TypeClass_ANY:
+ _destructAny( static_cast<uno_Any *>(pValue), release );
+ break;
+ case typelib_TypeClass_TYPEDEF:
+ OSL_FAIL( "### unexpected typedef!" );
+ break;
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ if (pTypeDescr)
+ {
+ _destructStruct( pValue, reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr), release );
+ }
+ else
+ {
+ TYPELIB_DANGER_GET( &pTypeDescr, pType );
+ _destructStruct( pValue, reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr), release );
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ }
+ break;
+ case typelib_TypeClass_SEQUENCE:
+ {
+ idestructSequence(
+ *static_cast<uno_Sequence **>(pValue), pType, pTypeDescr, release );
+ break;
+ }
+ case typelib_TypeClass_INTERFACE:
+ _release( *static_cast<void **>(pValue), release );
+ break;
+ default:
+ break;
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/eq.hxx b/cppu/source/uno/eq.hxx
new file mode 100644
index 000000000..60a372886
--- /dev/null
+++ b/cppu/source/uno/eq.hxx
@@ -0,0 +1,635 @@
+/* -*- 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 .
+ */
+#pragma once
+
+#include <cmath>
+#include <string.h>
+
+#include <o3tl/intcmp.hxx>
+#include <osl/diagnose.h>
+#include <rtl/ustring.hxx>
+
+#include "prim.hxx"
+
+
+namespace cppu
+{
+
+
+//#### equality ####################################################################################
+
+
+inline bool _equalObject(
+ void * pI1, void * pI2,
+ uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release )
+{
+ if (pI1 == pI2)
+ return true;
+ if ((nullptr == pI1) || (nullptr == pI2))
+ return false;
+ bool bRet = false;
+
+ typelib_TypeDescriptionReference * type_XInterface =
+ * typelib_static_type_getByTypeClass( typelib_TypeClass_INTERFACE );
+ if (nullptr == queryInterface)
+ queryInterface = binuno_queryInterface;
+ pI1 = (*queryInterface)( pI1, type_XInterface );
+ if (nullptr != pI1)
+ {
+ pI2 = (*queryInterface)( pI2, type_XInterface );
+ if (nullptr != pI2)
+ {
+ bRet = (pI1 == pI2);
+ _release( pI2, release );
+ }
+ _release( pI1, release );
+ }
+ return bRet;
+}
+
+
+bool equalStruct(
+ void * pDest, void *pSource,
+ typelib_CompoundTypeDescription * pTypeDescr,
+ uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release );
+
+inline bool _equalStruct(
+ void * pDest, void *pSource,
+ typelib_CompoundTypeDescription * pTypeDescr,
+ uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release )
+{
+ if (pTypeDescr->pBaseTypeDescription &&
+ !equalStruct( pDest, pSource, pTypeDescr->pBaseTypeDescription, queryInterface, release ))
+ {
+ return false;
+ }
+
+ typelib_TypeDescriptionReference ** ppTypeRefs = pTypeDescr->ppTypeRefs;
+ sal_Int32 * pMemberOffsets = pTypeDescr->pMemberOffsets;
+ sal_Int32 nDescr = pTypeDescr->nMembers;
+
+ while (nDescr--)
+ {
+ sal_Int32 nOffset = pMemberOffsets[nDescr];
+ if (! ::uno_type_equalData( static_cast<char *>(pDest) + nOffset,
+ ppTypeRefs[nDescr],
+ static_cast<char *>(pSource) + nOffset,
+ ppTypeRefs[nDescr],
+ queryInterface, release ))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool equalSequence(
+ uno_Sequence * pDest, uno_Sequence * pSource,
+ typelib_TypeDescriptionReference * pElementType,
+ uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release );
+
+inline bool _equalSequence(
+ uno_Sequence * pDest, uno_Sequence * pSource,
+ typelib_TypeDescriptionReference * pElementType,
+ uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release )
+{
+ if (pDest == pSource)
+ return true;
+ sal_Int32 nElements = pDest->nElements;
+ if (nElements != pSource->nElements)
+ return false;
+ if (! nElements)
+ return true;
+
+ void * pDestElements = pDest->elements;
+ void * pSourceElements = pSource->elements;
+
+ switch (pElementType->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ return (0 == memcmp( pDestElements, pSourceElements, sizeof(sal_Unicode) * nElements ));
+ case typelib_TypeClass_BOOLEAN:
+ {
+ for ( sal_Int32 nPos = nElements; nPos--; )
+ {
+ if (bool(static_cast<sal_Bool *>(pDestElements)[nPos]) !=
+ bool(static_cast<sal_Bool *>(pSourceElements)[nPos]))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ case typelib_TypeClass_BYTE:
+ return (0 == memcmp( pDestElements, pSourceElements, sizeof(sal_Int8) * nElements ));
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ return (0 == memcmp( pDestElements, pSourceElements, sizeof(sal_Int16) * nElements ));
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ return (0 == memcmp( pDestElements, pSourceElements, sizeof(sal_Int32) * nElements ));
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ return (0 == memcmp( pDestElements, pSourceElements, sizeof(sal_Int64) * nElements ));
+ case typelib_TypeClass_FLOAT:
+ {
+ for ( sal_Int32 nPos = nElements; nPos--; )
+ {
+ if (static_cast<float *>(pDestElements)[nPos] != static_cast<float *>(pSourceElements)[nPos])
+ return false;
+ }
+ return true;
+ }
+ case typelib_TypeClass_DOUBLE:
+ {
+ for ( sal_Int32 nPos = nElements; nPos--; )
+ {
+ if (static_cast<double *>(pDestElements)[nPos] != static_cast<double *>(pSourceElements)[nPos])
+ return false;
+ }
+ return true;
+ }
+ case typelib_TypeClass_STRING:
+ {
+ for ( sal_Int32 nPos = nElements; nPos--; )
+ {
+ if ( static_cast<OUString *>(pDestElements)[nPos] != static_cast<const OUString *>(pSourceElements)[nPos] )
+ return false;
+ }
+ return true;
+ }
+ case typelib_TypeClass_TYPE:
+ {
+ for ( sal_Int32 nPos = nElements; nPos--; )
+ {
+ if (! _type_equals( static_cast<typelib_TypeDescriptionReference **>(pDestElements)[nPos],
+ static_cast<typelib_TypeDescriptionReference **>(pSourceElements)[nPos] ))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ case typelib_TypeClass_ANY:
+ {
+ for ( sal_Int32 nPos = nElements; nPos--; )
+ {
+ uno_Any * pDest2 = static_cast<uno_Any *>(pDestElements) + nPos;
+ uno_Any * pSource2 = static_cast<uno_Any *>(pSourceElements) + nPos;
+ if (! ::uno_type_equalData( pDest2->pData, pDest2->pType,
+ pSource2->pData, pSource2->pType,
+ queryInterface, release ))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ case typelib_TypeClass_ENUM:
+ return (0 == memcmp( pDestElements, pSourceElements, sizeof(sal_Int32) * nElements ));
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ typelib_TypeDescription * pElementTypeDescr = nullptr;
+ TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
+ sal_Int32 nElementSize = pElementTypeDescr->nSize;
+ for ( sal_Int32 nPos = nElements; nPos--; )
+ {
+ if (! _equalStruct( static_cast<char *>(pDestElements) + (nPos * nElementSize),
+ static_cast<char *>(pSourceElements) + (nPos * nElementSize),
+ reinterpret_cast<typelib_CompoundTypeDescription *>(pElementTypeDescr),
+ queryInterface, release ))
+ {
+ TYPELIB_DANGER_RELEASE( pElementTypeDescr );
+ return false;
+ }
+ }
+ TYPELIB_DANGER_RELEASE( pElementTypeDescr );
+ return true;
+ }
+ case typelib_TypeClass_SEQUENCE: // sequence of sequence
+ {
+ typelib_TypeDescription * pElementTypeDescr = nullptr;
+ TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
+ typelib_TypeDescriptionReference * pSeqElementType =
+ reinterpret_cast<typelib_IndirectTypeDescription *>(pElementTypeDescr)->pType;
+ for ( sal_Int32 nPos = nElements; nPos--; )
+ {
+ if (! equalSequence( static_cast<uno_Sequence **>(pDestElements)[nPos],
+ static_cast<uno_Sequence **>(pSourceElements)[nPos],
+ pSeqElementType, queryInterface, release ))
+ {
+ TYPELIB_DANGER_RELEASE( pElementTypeDescr );
+ return false;
+ }
+ }
+ TYPELIB_DANGER_RELEASE( pElementTypeDescr );
+ return true;
+ }
+ case typelib_TypeClass_INTERFACE:
+ {
+ for ( sal_Int32 nPos = nElements; nPos--; )
+ {
+ if (! _equalObject( static_cast<void **>(pDestElements)[nPos], static_cast<void **>(pSourceElements)[nPos],
+ queryInterface, release ))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ default:
+ OSL_ASSERT(false);
+ return false;
+ }
+}
+
+inline bool _equalData(
+ void * pDest,
+ typelib_TypeDescriptionReference * pDestType, typelib_TypeDescription * pDestTypeDescr,
+ void * pSource,
+ typelib_TypeDescriptionReference * pSourceType,
+ uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release )
+{
+ typelib_TypeClass eSourceTypeClass, eDestTypeClass;
+ while (typelib_TypeClass_ANY == (eDestTypeClass = pDestType->eTypeClass))
+ {
+ pDestTypeDescr = nullptr;
+ pDestType = static_cast<uno_Any *>(pDest)->pType;
+ pDest = static_cast<uno_Any *>(pDest)->pData;
+ }
+ while (typelib_TypeClass_ANY == (eSourceTypeClass = pSourceType->eTypeClass))
+ {
+ pSourceType = static_cast<uno_Any *>(pSource)->pType;
+ pSource = static_cast<uno_Any *>(pSource)->pData;
+ }
+
+ switch (eDestTypeClass)
+ {
+ case typelib_TypeClass_VOID:
+ return eSourceTypeClass == typelib_TypeClass_VOID;
+ case typelib_TypeClass_CHAR:
+ return eSourceTypeClass == typelib_TypeClass_CHAR
+ && *static_cast<sal_Unicode *>(pDest) == *static_cast<sal_Unicode *>(pSource);
+ case typelib_TypeClass_BOOLEAN:
+ return eSourceTypeClass == typelib_TypeClass_BOOLEAN
+ && (bool(*static_cast<sal_Bool *>(pDest))
+ == bool(*static_cast<sal_Bool *>(pSource)));
+ case typelib_TypeClass_BYTE:
+ switch (eSourceTypeClass)
+ {
+ case typelib_TypeClass_BYTE:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int8 *>(pDest), *static_cast<sal_Int8 *>(pSource));
+ case typelib_TypeClass_SHORT:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int8 *>(pDest), *static_cast<sal_Int16 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int8 *>(pDest), *static_cast<sal_uInt16 *>(pSource));
+ case typelib_TypeClass_LONG:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int8 *>(pDest), *static_cast<sal_Int32 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_LONG:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int8 *>(pDest), *static_cast<sal_uInt32 *>(pSource));
+ case typelib_TypeClass_HYPER:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int8 *>(pDest), *static_cast<sal_Int64 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int8 *>(pDest), *static_cast<sal_Int64 *>(pSource));
+ case typelib_TypeClass_FLOAT:
+ return (static_cast<float>(*static_cast<sal_Int8 *>(pDest)) == *static_cast<float *>(pSource));
+ case typelib_TypeClass_DOUBLE:
+ return (static_cast<double>(*static_cast<sal_Int8 *>(pDest)) == *static_cast<double *>(pSource));
+ default:
+ return false;
+ }
+ case typelib_TypeClass_SHORT:
+ switch (eSourceTypeClass)
+ {
+ case typelib_TypeClass_BYTE:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int16 *>(pDest), *static_cast<sal_Int8 *>(pSource));
+ case typelib_TypeClass_SHORT:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int16 *>(pDest), *static_cast<sal_Int16 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int16 *>(pDest), *static_cast<sal_uInt16 *>(pSource));
+ case typelib_TypeClass_LONG:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int16 *>(pDest), *static_cast<sal_Int32 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_LONG:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int16 *>(pDest), *static_cast<sal_uInt32 *>(pSource));
+ case typelib_TypeClass_HYPER:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int16 *>(pDest), *static_cast<sal_Int64 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int16 *>(pDest), *static_cast<sal_Int64 *>(pSource));
+ case typelib_TypeClass_FLOAT:
+ return (static_cast<float>(*static_cast<sal_Int16 *>(pDest)) == *static_cast<float *>(pSource));
+ case typelib_TypeClass_DOUBLE:
+ return (static_cast<double>(*static_cast<sal_Int16 *>(pDest)) == *static_cast<double *>(pSource));
+ default:
+ return false;
+ }
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ switch (eSourceTypeClass)
+ {
+ case typelib_TypeClass_BYTE:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt16 *>(pDest), *static_cast<sal_Int8 *>(pSource));
+ case typelib_TypeClass_SHORT:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt16 *>(pDest), *static_cast<sal_Int16 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt16 *>(pDest), *static_cast<sal_uInt16 *>(pSource));
+ case typelib_TypeClass_LONG:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt16 *>(pDest), *static_cast<sal_Int32 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_LONG:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt16 *>(pDest), *static_cast<sal_uInt32 *>(pSource));
+ case typelib_TypeClass_HYPER:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt16 *>(pDest), *static_cast<sal_Int64 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt16 *>(pDest), *static_cast<sal_uInt64 *>(pSource));
+ case typelib_TypeClass_FLOAT:
+ return (static_cast<float>(*static_cast<sal_uInt16 *>(pDest)) == *static_cast<float *>(pSource));
+ case typelib_TypeClass_DOUBLE:
+ return (static_cast<double>(*static_cast<sal_uInt16 *>(pDest)) == *static_cast<double *>(pSource));
+ default:
+ return false;
+ }
+ case typelib_TypeClass_LONG:
+ switch (eSourceTypeClass)
+ {
+ case typelib_TypeClass_BYTE:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int32 *>(pDest), *static_cast<sal_Int8 *>(pSource));
+ case typelib_TypeClass_SHORT:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int32 *>(pDest), *static_cast<sal_Int16 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int32 *>(pDest), *static_cast<sal_uInt16 *>(pSource));
+ case typelib_TypeClass_LONG:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int32 *>(pDest), *static_cast<sal_Int32 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_LONG:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int32 *>(pDest), *static_cast<sal_uInt32 *>(pSource));
+ case typelib_TypeClass_HYPER:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int32 *>(pDest), *static_cast<sal_Int64 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int32 *>(pDest), *static_cast<sal_Int64 *>(pSource));
+ case typelib_TypeClass_FLOAT:
+ return (static_cast<float>(*static_cast<sal_Int32 *>(pDest)) == *static_cast<float *>(pSource));
+ case typelib_TypeClass_DOUBLE:
+ return (static_cast<double>(*static_cast<sal_Int32 *>(pDest)) == *static_cast<double *>(pSource));
+ default:
+ return false;
+ }
+ case typelib_TypeClass_UNSIGNED_LONG:
+ switch (eSourceTypeClass)
+ {
+ case typelib_TypeClass_BYTE:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt32 *>(pDest), *static_cast<sal_Int8 *>(pSource));
+ case typelib_TypeClass_SHORT:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt32 *>(pDest), *static_cast<sal_Int16 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt32 *>(pDest), *static_cast<sal_uInt16 *>(pSource));
+ case typelib_TypeClass_LONG:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt32 *>(pDest), *static_cast<sal_Int32 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_LONG:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt32 *>(pDest), *static_cast<sal_uInt32 *>(pSource));
+ case typelib_TypeClass_HYPER:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt32 *>(pDest), *static_cast<sal_Int64 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt32 *>(pDest), *static_cast<sal_uInt64 *>(pSource));
+ case typelib_TypeClass_FLOAT:
+ return (static_cast<float>(*static_cast<sal_uInt32 *>(pDest)) == *static_cast<float *>(pSource));
+ case typelib_TypeClass_DOUBLE:
+ return (static_cast<double>(*static_cast<sal_uInt32 *>(pDest)) == *static_cast<double *>(pSource));
+ default:
+ return false;
+ }
+ case typelib_TypeClass_HYPER:
+ switch (eSourceTypeClass)
+ {
+ case typelib_TypeClass_BYTE:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int64 *>(pDest), *static_cast<sal_Int8 *>(pSource));
+ case typelib_TypeClass_SHORT:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int64 *>(pDest), *static_cast<sal_Int16 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int64 *>(pDest), *static_cast<sal_uInt16 *>(pSource));
+ case typelib_TypeClass_LONG:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int64 *>(pDest), *static_cast<sal_Int32 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_LONG:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int64 *>(pDest), *static_cast<sal_uInt32 *>(pSource));
+ case typelib_TypeClass_HYPER:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int64 *>(pDest), *static_cast<sal_Int64 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ return o3tl::cmp_equal(
+ *static_cast<sal_Int64 *>(pDest), *static_cast<sal_Int64 *>(pSource));
+ case typelib_TypeClass_FLOAT:
+ return (static_cast<float>(*static_cast<sal_Int64 *>(pDest)) == *static_cast<float *>(pSource));
+ case typelib_TypeClass_DOUBLE:
+ return (static_cast<double>(*static_cast<sal_Int64 *>(pDest)) == *static_cast<double *>(pSource));
+ default:
+ return false;
+ }
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ switch (eSourceTypeClass)
+ {
+ case typelib_TypeClass_BYTE:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt64 *>(pDest), *static_cast<sal_Int8 *>(pSource));
+ case typelib_TypeClass_SHORT:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt64 *>(pDest), *static_cast<sal_Int16 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt64 *>(pDest), *static_cast<sal_uInt16 *>(pSource));
+ case typelib_TypeClass_LONG:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt64 *>(pDest), *static_cast<sal_Int32 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_LONG:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt64 *>(pDest), *static_cast<sal_uInt32 *>(pSource));
+ case typelib_TypeClass_HYPER:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt64 *>(pDest), *static_cast<sal_Int64 *>(pSource));
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ return o3tl::cmp_equal(
+ *static_cast<sal_uInt64 *>(pDest), *static_cast<sal_uInt64 *>(pSource));
+ case typelib_TypeClass_FLOAT:
+ if (::floor( *static_cast<float *>(pSource) ) != *static_cast<float *>(pSource) || *static_cast<float *>(pSource) < 0)
+ return false;
+ return (*static_cast<sal_uInt64 *>(pDest) == static_cast<sal_uInt64>(*static_cast<float *>(pSource)));
+ case typelib_TypeClass_DOUBLE:
+ if (::floor( *static_cast<double *>(pSource) ) != *static_cast<double *>(pSource) || *static_cast<double *>(pSource) < 0)
+ return false;
+ return (*static_cast<sal_uInt64 *>(pDest) == static_cast<sal_uInt64>(*static_cast<double *>(pSource)));
+ default:
+ return false;
+ }
+ case typelib_TypeClass_FLOAT:
+ switch (eSourceTypeClass)
+ {
+ case typelib_TypeClass_BYTE:
+ return (*static_cast<float *>(pDest) == static_cast<float>(*static_cast<sal_Int8 *>(pSource)));
+ case typelib_TypeClass_SHORT:
+ return (*static_cast<float *>(pDest) == static_cast<float>(*static_cast<sal_Int16 *>(pSource)));
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ return (*static_cast<float *>(pDest) == static_cast<float>(*static_cast<sal_uInt16 *>(pSource)));
+ case typelib_TypeClass_LONG:
+ return (*static_cast<float *>(pDest) == static_cast<float>(*static_cast<sal_Int32 *>(pSource)));
+ case typelib_TypeClass_UNSIGNED_LONG:
+ return (*static_cast<float *>(pDest) == static_cast<float>(*static_cast<sal_uInt32 *>(pSource)));
+ case typelib_TypeClass_HYPER:
+ return (*static_cast<float *>(pDest) == static_cast<float>(*static_cast<sal_Int64 *>(pSource)));
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ if (::floor( *static_cast<float *>(pDest) ) != *static_cast<float *>(pDest) || *static_cast<float *>(pDest) < 0)
+ return false;
+ return (static_cast<sal_uInt64>(*static_cast<float *>(pDest)) == *static_cast<sal_uInt64 *>(pSource));
+ case typelib_TypeClass_FLOAT:
+ return (*static_cast<float *>(pDest) == *static_cast<float *>(pSource));
+ case typelib_TypeClass_DOUBLE:
+ return (static_cast<double>(*static_cast<float *>(pDest)) == *static_cast<double *>(pSource));
+ default:
+ return false;
+ }
+ case typelib_TypeClass_DOUBLE:
+ switch (eSourceTypeClass)
+ {
+ case typelib_TypeClass_BYTE:
+ return (*static_cast<double *>(pDest) == static_cast<double>(*static_cast<sal_Int8 *>(pSource)));
+ case typelib_TypeClass_SHORT:
+ return (*static_cast<double *>(pDest) == static_cast<double>(*static_cast<sal_Int16 *>(pSource)));
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ return (*static_cast<double *>(pDest) == static_cast<double>(*static_cast<sal_uInt16 *>(pSource)));
+ case typelib_TypeClass_LONG:
+ return (*static_cast<double *>(pDest) == static_cast<double>(*static_cast<sal_Int32 *>(pSource)));
+ case typelib_TypeClass_UNSIGNED_LONG:
+ return (*static_cast<double *>(pDest) == static_cast<double>(*static_cast<sal_uInt32 *>(pSource)));
+ case typelib_TypeClass_HYPER:
+ return (*static_cast<double *>(pDest) == static_cast<double>(*static_cast<sal_Int64 *>(pSource)));
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ if (::floor( *static_cast<double *>(pDest) ) != *static_cast<double *>(pDest) || *static_cast<double *>(pDest) < 0)
+ return false;
+ return (static_cast<sal_uInt64>(*static_cast<double *>(pDest)) == *static_cast<sal_uInt64 *>(pSource));
+ case typelib_TypeClass_FLOAT:
+ return (*static_cast<double *>(pDest) == static_cast<double>(*static_cast<float *>(pSource)));
+ case typelib_TypeClass_DOUBLE:
+ return (*static_cast<double *>(pDest) == *static_cast<double *>(pSource));
+ default:
+ return false;
+ }
+ case typelib_TypeClass_STRING:
+ return eSourceTypeClass == typelib_TypeClass_STRING
+ && *static_cast<OUString *>(pDest) ==
+ *static_cast<OUString const *>(pSource);
+ case typelib_TypeClass_TYPE:
+ return eSourceTypeClass == typelib_TypeClass_TYPE
+ && _type_equals(
+ *static_cast<typelib_TypeDescriptionReference **>(pDest),
+ *static_cast<typelib_TypeDescriptionReference **>(pSource) );
+ case typelib_TypeClass_ENUM:
+ return (_type_equals( pDestType, pSourceType ) &&
+ *static_cast<sal_Int32 *>(pDest) == *static_cast<sal_Int32 *>(pSource));
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ if (! _type_equals( pDestType, pSourceType ))
+ return false;
+ if (pDestTypeDescr)
+ {
+ return _equalStruct(
+ pDest, pSource,
+ reinterpret_cast<typelib_CompoundTypeDescription *>(pDestTypeDescr),
+ queryInterface, release );
+ }
+ else
+ {
+ TYPELIB_DANGER_GET( &pDestTypeDescr, pDestType );
+ bool bRet = _equalStruct(
+ pDest, pSource,
+ reinterpret_cast<typelib_CompoundTypeDescription *>(pDestTypeDescr),
+ queryInterface, release );
+ TYPELIB_DANGER_RELEASE( pDestTypeDescr );
+ return bRet;
+ }
+ case typelib_TypeClass_SEQUENCE:
+ if (_type_equals( pDestType, pSourceType ))
+ {
+ if (pDestTypeDescr)
+ {
+ return _equalSequence(
+ *static_cast<uno_Sequence **>(pDest), *static_cast<uno_Sequence **>(pSource),
+ reinterpret_cast<typelib_IndirectTypeDescription *>(pDestTypeDescr)->pType,
+ queryInterface, release );
+ }
+ else
+ {
+ TYPELIB_DANGER_GET( &pDestTypeDescr, pDestType );
+ bool bRet = _equalSequence(
+ *static_cast<uno_Sequence **>(pDest), *static_cast<uno_Sequence **>(pSource),
+ reinterpret_cast<typelib_IndirectTypeDescription *>(pDestTypeDescr)->pType,
+ queryInterface, release );
+ TYPELIB_DANGER_RELEASE( pDestTypeDescr );
+ return bRet;
+ }
+ }
+ return false;
+ case typelib_TypeClass_INTERFACE:
+ if (typelib_TypeClass_INTERFACE == eSourceTypeClass)
+ return _equalObject( *static_cast<void **>(pDest), *static_cast<void **>(pSource), queryInterface, release );
+ break;
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
+ return false;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/lbenv.cxx b/cppu/source/uno/lbenv.cxx
new file mode 100644
index 000000000..dd29951a6
--- /dev/null
+++ b/cppu/source/uno/lbenv.cxx
@@ -0,0 +1,1147 @@
+/* -*- 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 .
+ */
+
+#ifdef DISABLE_DYNLOADING
+#include <config_java.h>
+#endif
+
+#include <cppu/EnvDcp.hxx>
+
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <osl/interlck.h>
+#include <osl/mutex.hxx>
+#include <osl/module.hxx>
+#include <osl/process.h>
+#include <rtl/process.h>
+#include <rtl/string.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <typelib/typedescription.h>
+#include <uno/dispatcher.h>
+#include <uno/environment.h>
+#include <uno/lbnames.h>
+#include "prim.hxx"
+#include "loadmodule.hxx"
+
+#include <string_view>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+#include <stdio.h>
+
+
+namespace
+{
+
+
+bool td_equals( typelib_InterfaceTypeDescription const * pTD1,
+ typelib_InterfaceTypeDescription const * pTD2 )
+{
+ return (pTD1 == pTD2 ||
+ (pTD1->aBase.pTypeName->length == pTD2->aBase.pTypeName->length &&
+ ::rtl_ustr_compare(
+ pTD1->aBase.pTypeName->buffer,
+ pTD2->aBase.pTypeName->buffer ) == 0));
+}
+
+struct uno_DefaultEnvironment;
+
+
+struct InterfaceEntry
+{
+ sal_Int32 refCount;
+ void * pInterface;
+ uno_freeProxyFunc fpFreeProxy;
+ typelib_InterfaceTypeDescription * pTypeDescr;
+};
+
+struct ObjectEntry
+{
+ OUString oid;
+ std::vector< InterfaceEntry > aInterfaces;
+ sal_Int32 nRef;
+ bool mixedObject;
+
+ explicit ObjectEntry( OUString aOId_ );
+
+ void append(
+ uno_DefaultEnvironment * pEnv,
+ void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr,
+ uno_freeProxyFunc fpFreeProxy );
+ InterfaceEntry * find(
+ typelib_InterfaceTypeDescription * pTypeDescr );
+ sal_Int32 find( void const * iface_ptr, std::size_t pos ) const;
+};
+
+
+struct FctPtrHash
+{
+ std::size_t operator () ( const void * pKey ) const
+ { return reinterpret_cast< std::size_t>( pKey ); }
+};
+
+
+// mapping from environment name to environment
+typedef std::unordered_map<
+ OUString, uno_Environment * > OUString2EnvironmentMap;
+
+// mapping from ptr to object entry
+typedef std::unordered_map<
+ void *, ObjectEntry *, FctPtrHash > Ptr2ObjectMap;
+// mapping from oid to object entry
+typedef std::unordered_map<
+ OUString, ObjectEntry * > OId2ObjectMap;
+
+struct EnvironmentsData
+{
+ ::osl::Mutex mutex;
+ OUString2EnvironmentMap aName2EnvMap;
+
+ EnvironmentsData() : isDisposing(false) {}
+ ~EnvironmentsData();
+
+ void getEnvironment(
+ uno_Environment ** ppEnv, std::u16string_view rEnvDcp, void * pContext );
+ void registerEnvironment( uno_Environment ** ppEnv );
+ void getRegisteredEnvironments(
+ uno_Environment *** pppEnvs, sal_Int32 * pnLen,
+ uno_memAlloc memAlloc, std::u16string_view rEnvDcp );
+
+ bool isDisposing;
+};
+
+EnvironmentsData& theEnvironmentsData()
+{
+ static EnvironmentsData SINGLETON;
+ return SINGLETON;
+}
+
+struct uno_DefaultEnvironment : public uno_ExtEnvironment
+{
+ sal_Int32 nRef;
+ sal_Int32 nWeakRef;
+
+ ::osl::Mutex mutex;
+ Ptr2ObjectMap aPtr2ObjectMap;
+ OId2ObjectMap aOId2ObjectMap;
+
+ uno_DefaultEnvironment(
+ const OUString & rEnvDcp_, void * pContext_ );
+ ~uno_DefaultEnvironment();
+};
+
+
+ObjectEntry::ObjectEntry( OUString aOId_ )
+ : oid(std::move( aOId_ )),
+ nRef( 0 ),
+ mixedObject( false )
+{
+ aInterfaces.reserve( 2 );
+}
+
+
+void ObjectEntry::append(
+ uno_DefaultEnvironment * pEnv,
+ void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr,
+ uno_freeProxyFunc fpFreeProxy )
+{
+ InterfaceEntry aNewEntry;
+ if (! fpFreeProxy)
+ (*pEnv->acquireInterface)( pEnv, pInterface );
+ aNewEntry.refCount = 1;
+ aNewEntry.pInterface = pInterface;
+ aNewEntry.fpFreeProxy = fpFreeProxy;
+ typelib_typedescription_acquire( &pTypeDescr->aBase );
+ aNewEntry.pTypeDescr = pTypeDescr;
+
+ std::pair< Ptr2ObjectMap::iterator, bool > i(
+ pEnv->aPtr2ObjectMap.emplace( pInterface, this ) );
+ SAL_WARN_IF(
+ !i.second && (find(pInterface, 0) == -1 || i.first->second != this),
+ "cppu",
+ "map already contains " << i.first->second << " != " << this << " for "
+ << pInterface);
+ aInterfaces.push_back( aNewEntry );
+}
+
+
+InterfaceEntry * ObjectEntry::find(
+ typelib_InterfaceTypeDescription * pTypeDescr_ )
+{
+ OSL_ASSERT( ! aInterfaces.empty() );
+ if (aInterfaces.empty())
+ return nullptr;
+
+ // shortcut common case:
+ OUString const & type_name =
+ OUString::unacquired( &pTypeDescr_->aBase.pTypeName );
+ if ( type_name == "com.sun.star.uno.XInterface" )
+ {
+ return aInterfaces.data();
+ }
+
+ std::size_t nSize = aInterfaces.size();
+ for ( std::size_t nPos = 0; nPos < nSize; ++nPos )
+ {
+ typelib_InterfaceTypeDescription * pITD =
+ aInterfaces[ nPos ].pTypeDescr;
+ while (pITD)
+ {
+ if (td_equals( pITD, pTypeDescr_ ))
+ return &aInterfaces[ nPos ];
+ pITD = pITD->pBaseTypeDescription;
+ }
+ }
+ return nullptr;
+}
+
+
+sal_Int32 ObjectEntry::find(
+ void const * iface_ptr, std::size_t pos ) const
+{
+ std::size_t size = aInterfaces.size();
+ for ( ; pos < size; ++pos )
+ {
+ if (aInterfaces[ pos ].pInterface == iface_ptr)
+ return pos;
+ }
+ return -1;
+}
+
+extern "C"
+{
+
+
+static void defenv_registerInterface(
+ uno_ExtEnvironment * pEnv, void ** ppInterface,
+ rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
+{
+ OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" );
+ OUString const & rOId = OUString::unacquired( &pOId );
+
+ uno_DefaultEnvironment * that =
+ static_cast< uno_DefaultEnvironment * >( pEnv );
+ ::osl::ClearableMutexGuard guard( that->mutex );
+
+ // try to insert dummy 0:
+ std::pair<OId2ObjectMap::iterator, bool> const insertion(
+ that->aOId2ObjectMap.emplace( rOId, nullptr ) );
+ if (insertion.second)
+ {
+ ObjectEntry * pOEntry = new ObjectEntry( rOId );
+ insertion.first->second = pOEntry;
+ ++pOEntry->nRef; // another register call on object
+ pOEntry->append( that, *ppInterface, pTypeDescr, nullptr );
+ }
+ else // object entry exists
+ {
+ ObjectEntry * pOEntry = insertion.first->second;
+ ++pOEntry->nRef; // another register call on object
+ InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr );
+
+ if (pIEntry) // type entry exists
+ {
+ ++pIEntry->refCount;
+ if (pIEntry->pInterface != *ppInterface)
+ {
+ void * pInterface = pIEntry->pInterface;
+ (*pEnv->acquireInterface)( pEnv, pInterface );
+ guard.clear();
+ (*pEnv->releaseInterface)( pEnv, *ppInterface );
+ *ppInterface = pInterface;
+ }
+ }
+ else
+ {
+ pOEntry->append( that, *ppInterface, pTypeDescr, nullptr );
+ }
+ }
+}
+
+
+static void defenv_registerProxyInterface(
+ uno_ExtEnvironment * pEnv, void ** ppInterface, uno_freeProxyFunc freeProxy,
+ rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
+{
+ OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr && freeProxy,
+ "### null ptr!" );
+ OUString const & rOId = OUString::unacquired( &pOId );
+
+ uno_DefaultEnvironment * that =
+ static_cast< uno_DefaultEnvironment * >( pEnv );
+ ::osl::ClearableMutexGuard guard( that->mutex );
+
+ // try to insert dummy 0:
+ std::pair<OId2ObjectMap::iterator, bool> const insertion(
+ that->aOId2ObjectMap.emplace( rOId, nullptr ) );
+ if (insertion.second)
+ {
+ ObjectEntry * pOEntry = new ObjectEntry( rOId );
+ insertion.first->second = pOEntry;
+ ++pOEntry->nRef; // another register call on object
+ pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy );
+ }
+ else // object entry exists
+ {
+ ObjectEntry * pOEntry = insertion.first->second;
+
+ // first registration was an original, then registerProxyInterface():
+ pOEntry->mixedObject |=
+ (!pOEntry->aInterfaces.empty() &&
+ pOEntry->aInterfaces[ 0 ].fpFreeProxy == nullptr);
+
+ ++pOEntry->nRef; // another register call on object
+ InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr );
+
+ if (pIEntry) // type entry exists
+ {
+ if (pIEntry->pInterface == *ppInterface)
+ {
+ ++pIEntry->refCount;
+ }
+ else
+ {
+ void * pInterface = pIEntry->pInterface;
+ (*pEnv->acquireInterface)( pEnv, pInterface );
+ --pOEntry->nRef; // manual revoke of proxy to be freed
+ guard.clear();
+ (*freeProxy)( pEnv, *ppInterface );
+ *ppInterface = pInterface;
+ }
+ }
+ else
+ {
+ pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy );
+ }
+ }
+}
+
+
+static void s_stub_defenv_revokeInterface(va_list * pParam)
+{
+ uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
+ void * pInterface = va_arg(*pParam, void *);
+
+ OSL_ENSURE( pEnv && pInterface, "### null ptr!" );
+ uno_DefaultEnvironment * that =
+ static_cast< uno_DefaultEnvironment * >( pEnv );
+ ::osl::ClearableMutexGuard guard( that->mutex );
+
+ Ptr2ObjectMap::const_iterator const iFind(
+ that->aPtr2ObjectMap.find( pInterface ) );
+ OSL_ASSERT( iFind != that->aPtr2ObjectMap.end() );
+ ObjectEntry * pOEntry = iFind->second;
+ if (! --pOEntry->nRef)
+ {
+ // cleanup maps
+ that->aOId2ObjectMap.erase( pOEntry->oid );
+ sal_Int32 nPos;
+ for ( nPos = pOEntry->aInterfaces.size(); nPos--; )
+ {
+ that->aPtr2ObjectMap.erase( pOEntry->aInterfaces[nPos].pInterface );
+ }
+
+ // the last proxy interface of the environment might kill this
+ // environment, because of releasing its language binding!!!
+ guard.clear();
+
+ // release interfaces
+ for ( nPos = pOEntry->aInterfaces.size(); nPos--; )
+ {
+ InterfaceEntry const & rEntry = pOEntry->aInterfaces[nPos];
+ typelib_typedescription_release( &rEntry.pTypeDescr->aBase );
+ if (rEntry.fpFreeProxy) // is proxy or used interface?
+ {
+ (*rEntry.fpFreeProxy)( pEnv, rEntry.pInterface );
+ }
+ else
+ {
+ (*pEnv->releaseInterface)( pEnv, rEntry.pInterface );
+ }
+ }
+
+ delete pOEntry;
+ }
+ else if (pOEntry->mixedObject)
+ {
+ OSL_ASSERT( !pOEntry->aInterfaces.empty() &&
+ pOEntry->aInterfaces[ 0 ].fpFreeProxy == nullptr );
+
+ sal_Int32 index = pOEntry->find( pInterface, 1 );
+ OSL_ASSERT( index > 0 );
+ if (index > 0)
+ {
+ InterfaceEntry & entry = pOEntry->aInterfaces[ index ];
+ OSL_ASSERT( entry.pInterface == pInterface );
+ if (entry.fpFreeProxy != nullptr)
+ {
+ --entry.refCount;
+ if (entry.refCount == 0)
+ {
+ uno_freeProxyFunc fpFreeProxy = entry.fpFreeProxy;
+ typelib_TypeDescription * pTypeDescr =
+ reinterpret_cast< typelib_TypeDescription * >(
+ entry.pTypeDescr );
+
+ pOEntry->aInterfaces.erase(
+ pOEntry->aInterfaces.begin() + index );
+ if (pOEntry->find( pInterface, index ) < 0)
+ {
+ // proxy ptr not registered for another interface:
+ // remove from ptr map
+ std::size_t erased =
+ that->aPtr2ObjectMap.erase( pInterface );
+ OSL_ASSERT( erased == 1 );
+ }
+
+ guard.clear();
+
+ typelib_typedescription_release( pTypeDescr );
+ (*fpFreeProxy)( pEnv, pInterface );
+ }
+ }
+ }
+ }
+}
+
+static void defenv_revokeInterface(uno_ExtEnvironment * pEnv, void * pInterface)
+{
+ uno_Environment_invoke(&pEnv->aBase, s_stub_defenv_revokeInterface, pEnv, pInterface);
+}
+
+
+static void defenv_getObjectIdentifier(
+ uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
+{
+ OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" );
+ if (*ppOId)
+ {
+ ::rtl_uString_release( *ppOId );
+ *ppOId = nullptr;
+ }
+
+ uno_DefaultEnvironment * that =
+ static_cast< uno_DefaultEnvironment * >( pEnv );
+ ::osl::ClearableMutexGuard guard( that->mutex );
+
+ Ptr2ObjectMap::const_iterator const iFind(
+ that->aPtr2ObjectMap.find( pInterface ) );
+ if (iFind == that->aPtr2ObjectMap.end())
+ {
+ guard.clear();
+ (*pEnv->computeObjectIdentifier)( pEnv, ppOId, pInterface );
+ }
+ else
+ {
+ rtl_uString * hstr = iFind->second->oid.pData;
+ rtl_uString_acquire( hstr );
+ *ppOId = hstr;
+ }
+}
+
+
+static void defenv_getRegisteredInterface(
+ uno_ExtEnvironment * pEnv, void ** ppInterface,
+ rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
+{
+ OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" );
+ if (*ppInterface)
+ {
+ (*pEnv->releaseInterface)( pEnv, *ppInterface );
+ *ppInterface = nullptr;
+ }
+
+ OUString const & rOId = OUString::unacquired( &pOId );
+ uno_DefaultEnvironment * that =
+ static_cast< uno_DefaultEnvironment * >( pEnv );
+ ::osl::MutexGuard guard( that->mutex );
+
+ OId2ObjectMap::const_iterator const iFind
+ ( that->aOId2ObjectMap.find( rOId ) );
+ if (iFind != that->aOId2ObjectMap.end())
+ {
+ InterfaceEntry const * pIEntry = iFind->second->find( pTypeDescr );
+ if (pIEntry)
+ {
+ (*pEnv->acquireInterface)( pEnv, pIEntry->pInterface );
+ *ppInterface = pIEntry->pInterface;
+ }
+ }
+}
+
+
+static void defenv_getRegisteredInterfaces(
+ uno_ExtEnvironment * pEnv, void *** pppInterfaces, sal_Int32 * pnLen,
+ uno_memAlloc memAlloc )
+{
+ assert(pEnv && pppInterfaces && pnLen && memAlloc && "### null ptr!");
+ uno_DefaultEnvironment * that =
+ static_cast< uno_DefaultEnvironment * >( pEnv );
+ ::osl::MutexGuard guard( that->mutex );
+
+ sal_Int32 nLen = that->aPtr2ObjectMap.size();
+ sal_Int32 nPos = 0;
+ void ** ppInterfaces = static_cast<void **>((*memAlloc)( nLen * sizeof (void *) ));
+
+ for (const auto& rEntry : that->aPtr2ObjectMap)
+ {
+ ppInterfaces[nPos] = rEntry.first;
+ (*pEnv->acquireInterface)( pEnv, ppInterfaces[nPos] );
+ nPos++;
+ }
+
+ *pppInterfaces = ppInterfaces;
+ *pnLen = nLen;
+}
+
+
+static void defenv_acquire( uno_Environment * pEnv )
+{
+ uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
+ osl_atomic_increment( &that->nWeakRef );
+ osl_atomic_increment( &that->nRef );
+}
+
+
+static void defenv_release( uno_Environment * pEnv )
+{
+ uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
+ if (! osl_atomic_decrement( &that->nRef ))
+ {
+ // invoke dispose callback
+ if (pEnv->environmentDisposing)
+ {
+ (*pEnv->environmentDisposing)( pEnv );
+ }
+
+ OSL_ENSURE( that->aOId2ObjectMap.empty(), "### object entries left!" );
+ }
+ // free memory if no weak refs left
+ if (! osl_atomic_decrement( &that->nWeakRef ))
+ {
+ delete that;
+ }
+}
+
+
+static void defenv_acquireWeak( uno_Environment * pEnv )
+{
+ uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
+ osl_atomic_increment( &that->nWeakRef );
+}
+
+
+static void defenv_releaseWeak( uno_Environment * pEnv )
+{
+ uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
+ if (! osl_atomic_decrement( &that->nWeakRef ))
+ {
+ delete that;
+ }
+}
+
+
+static void defenv_harden(
+ uno_Environment ** ppHardEnv, uno_Environment * pEnv )
+{
+ if (*ppHardEnv)
+ {
+ (*(*ppHardEnv)->release)( *ppHardEnv );
+ *ppHardEnv = nullptr;
+ }
+
+ EnvironmentsData & rData = theEnvironmentsData();
+
+ if (rData.isDisposing)
+ return;
+
+ uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
+ {
+ ::osl::MutexGuard guard( rData.mutex );
+ if (1 == osl_atomic_increment( &that->nRef )) // is dead
+ {
+ that->nRef = 0;
+ return;
+ }
+ }
+ osl_atomic_increment( &that->nWeakRef );
+ *ppHardEnv = pEnv;
+}
+
+
+static void defenv_dispose( SAL_UNUSED_PARAMETER uno_Environment * )
+{
+}
+}
+
+
+uno_DefaultEnvironment::uno_DefaultEnvironment(
+ const OUString & rEnvDcp_, void * pContext_ )
+ : nRef( 0 ),
+ nWeakRef( 0 )
+{
+ uno_Environment * that = reinterpret_cast< uno_Environment * >(this);
+ that->pReserved = nullptr;
+ // functions
+ that->acquire = defenv_acquire;
+ that->release = defenv_release;
+ that->acquireWeak = defenv_acquireWeak;
+ that->releaseWeak = defenv_releaseWeak;
+ that->harden = defenv_harden;
+ that->dispose = defenv_dispose;
+ that->pExtEnv = this;
+ // identifier
+ ::rtl_uString_acquire( rEnvDcp_.pData );
+ that->pTypeName = rEnvDcp_.pData;
+ that->pContext = pContext_;
+
+ // will be late initialized
+ that->environmentDisposing = nullptr;
+
+ uno_ExtEnvironment::registerInterface = defenv_registerInterface;
+ uno_ExtEnvironment::registerProxyInterface = defenv_registerProxyInterface;
+ uno_ExtEnvironment::revokeInterface = defenv_revokeInterface;
+ uno_ExtEnvironment::getObjectIdentifier = defenv_getObjectIdentifier;
+ uno_ExtEnvironment::getRegisteredInterface = defenv_getRegisteredInterface;
+ uno_ExtEnvironment::getRegisteredInterfaces =
+ defenv_getRegisteredInterfaces;
+
+}
+
+
+uno_DefaultEnvironment::~uno_DefaultEnvironment()
+{
+ ::rtl_uString_release( aBase.pTypeName );
+}
+
+
+void writeLine(
+ void * stream, const char * pLine, const char * pFilter )
+{
+ if (pFilter && *pFilter)
+ {
+ // lookup pFilter in pLine
+ while (*pLine)
+ {
+ if (*pLine == *pFilter)
+ {
+ sal_Int32 nPos = 1;
+ while (pLine[nPos] && pFilter[nPos] == pLine[nPos])
+ {
+ ++nPos;
+ }
+ if (! pFilter[nPos])
+ {
+ if (stream)
+ {
+ fprintf( static_cast<FILE *>(stream), "%s\n", pLine );
+ }
+ else
+ {
+ SAL_WARN("cppu", pLine );
+ }
+ }
+ }
+ ++pLine;
+ }
+ }
+ else
+ {
+ if (stream)
+ {
+ fprintf( static_cast<FILE *>(stream), "%s\n", pLine );
+ }
+ else
+ {
+ fprintf( stderr, "%s\n", pLine );
+ }
+ }
+}
+
+
+void writeLine(
+ void * stream, std::u16string_view rLine, const char * pFilter )
+{
+ OString aLine( OUStringToOString(
+ rLine, RTL_TEXTENCODING_ASCII_US ) );
+ writeLine( stream, aLine.getStr(), pFilter );
+}
+
+}
+
+extern "C" void SAL_CALL uno_dumpEnvironment(
+ void * stream, uno_Environment * pEnv, const char * pFilter )
+ SAL_THROW_EXTERN_C()
+{
+ OSL_ENSURE( pEnv, "### null ptr!" );
+ OUStringBuffer buf;
+
+ if (! pEnv->pExtEnv)
+ {
+ writeLine( stream, "###################################"
+ "###########################################", pFilter );
+ buf.append( "environment: " );
+ buf.append( pEnv->pTypeName );
+ writeLine( stream, buf.makeStringAndClear(), pFilter );
+ writeLine( stream, "NO INTERFACE INFORMATION AVAILABLE!", pFilter );
+ return;
+ }
+
+ writeLine( stream, "########################################"
+ "######################################", pFilter );
+ buf.append( "environment dump: " );
+ buf.append( pEnv->pTypeName );
+ writeLine( stream, buf.makeStringAndClear(), pFilter );
+
+ uno_DefaultEnvironment * that =
+ reinterpret_cast< uno_DefaultEnvironment * >(pEnv);
+ ::osl::MutexGuard guard( that->mutex );
+
+ Ptr2ObjectMap ptr2obj( that->aPtr2ObjectMap );
+ for (const auto& rEntry : that->aOId2ObjectMap)
+ {
+ ObjectEntry * pOEntry = rEntry.second;
+
+ buf.append( "+ " );
+ if (pOEntry->mixedObject)
+ buf.append( "mixed " );
+ buf.append( "object entry: nRef=" );
+ buf.append( pOEntry->nRef );
+ buf.append( "; oid=\"" );
+ buf.append( pOEntry->oid );
+ buf.append( '\"' );
+ writeLine( stream, buf.makeStringAndClear(), pFilter );
+
+ for ( std::size_t nPos = 0;
+ nPos < pOEntry->aInterfaces.size(); ++nPos )
+ {
+ const InterfaceEntry & rIEntry = pOEntry->aInterfaces[nPos];
+
+ buf.append( " - " );
+ buf.append( rIEntry.pTypeDescr->aBase.pTypeName );
+ if (rIEntry.fpFreeProxy)
+ {
+ buf.append( "; proxy free=0x" );
+ buf.append(
+ reinterpret_cast< sal_IntPtr >(rIEntry.fpFreeProxy), 16 );
+ }
+ else
+ {
+ buf.append( "; original" );
+ }
+ buf.append( "; ptr=0x" );
+ buf.append(
+ reinterpret_cast< sal_IntPtr >(rIEntry.pInterface), 16 );
+
+ if (pOEntry->find( rIEntry.pInterface, nPos + 1 ) < 0)
+ {
+ std::size_t erased = ptr2obj.erase( rIEntry.pInterface );
+ if (erased != 1)
+ {
+ buf.append( " (ptr not found in map!)" );
+ }
+ }
+ writeLine( stream, buf.makeStringAndClear(), pFilter );
+ }
+ }
+ if (! ptr2obj.empty())
+ writeLine( stream, "ptr map inconsistency!!!", pFilter );
+ writeLine( stream, "#####################################"
+ "#########################################", pFilter );
+}
+
+
+extern "C" void SAL_CALL uno_dumpEnvironmentByName(
+ void * stream, rtl_uString * pEnvDcp, const char * pFilter )
+ SAL_THROW_EXTERN_C()
+{
+ uno_Environment * pEnv = nullptr;
+ uno_getEnvironment( &pEnv, pEnvDcp, nullptr );
+ if (pEnv)
+ {
+ ::uno_dumpEnvironment( stream, pEnv, pFilter );
+ (*pEnv->release)( pEnv );
+ }
+ else
+ {
+ writeLine(
+ stream,
+ OUStringConcatenation("environment \"" + OUString::unacquired(&pEnvDcp) + "\" does not exist!"),
+ pFilter );
+ }
+}
+
+namespace
+{
+
+const OUString & unoenv_getStaticOIdPart()
+{
+ static auto const theStaticOIdPart = [] {
+ OUStringBuffer aRet( 64 );
+ aRet.append( "];" );
+ // pid
+ oslProcessInfo info;
+ info.Size = sizeof(oslProcessInfo);
+ if (::osl_getProcessInfo( nullptr, osl_Process_IDENTIFIER, &info ) ==
+ osl_Process_E_None)
+ {
+ aRet.append( static_cast<sal_Int64>(info.Ident), 16 );
+ }
+ else
+ {
+ aRet.append( "unknown process id" );
+ }
+ // good guid
+ sal_uInt8 ar[16];
+ ::rtl_getGlobalProcessId( ar );
+ aRet.append( ';' );
+ for (unsigned char i : ar)
+ aRet.append( static_cast<sal_Int32>(i), 16 );
+
+ return aRet.makeStringAndClear();
+ }();
+ return theStaticOIdPart;
+}
+
+}
+
+extern "C"
+{
+
+
+static void unoenv_computeObjectIdentifier(
+ uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
+{
+ assert(pEnv && ppOId && pInterface && "### null ptr!");
+ if (*ppOId)
+ {
+ ::rtl_uString_release( *ppOId );
+ *ppOId = nullptr;
+ }
+
+ uno_Interface * pUnoI = static_cast<uno_Interface *>(
+ ::cppu::binuno_queryInterface(
+ pInterface, *typelib_static_type_getByTypeClass(
+ typelib_TypeClass_INTERFACE ) ));
+ if (nullptr == pUnoI)
+ return;
+
+ (*pUnoI->release)( pUnoI );
+ OUString aStr(
+ // interface
+ OUString::number( reinterpret_cast< sal_Int64 >(pUnoI), 16 ) + ";"
+ // environment[context]
+ + OUString::unacquired(&pEnv->aBase.pTypeName) + "["
+ + OUString::number( reinterpret_cast< sal_Int64 >(
+ reinterpret_cast<
+ uno_Environment * >(pEnv)->pContext ), 16 )
+ // process;good guid
+ + unoenv_getStaticOIdPart() );
+ *ppOId = aStr.pData;
+ ::rtl_uString_acquire( *ppOId );
+}
+
+
+static void unoenv_acquireInterface(
+ SAL_UNUSED_PARAMETER uno_ExtEnvironment *, void * pUnoI_ )
+{
+ uno_Interface * pUnoI = static_cast< uno_Interface * >(pUnoI_);
+ (*pUnoI->acquire)( pUnoI );
+}
+
+
+static void unoenv_releaseInterface(
+ SAL_UNUSED_PARAMETER uno_ExtEnvironment *, void * pUnoI_ )
+{
+ uno_Interface * pUnoI = static_cast< uno_Interface * >(pUnoI_);
+ (*pUnoI->release)( pUnoI );
+}
+}
+
+namespace {
+
+EnvironmentsData::~EnvironmentsData()
+{
+ ::osl::MutexGuard guard( mutex );
+ isDisposing = true;
+
+ for ( const auto& rEntry : aName2EnvMap )
+ {
+ uno_Environment * pWeak = rEntry.second;
+ uno_Environment * pHard = nullptr;
+ (*pWeak->harden)( &pHard, pWeak );
+ (*pWeak->releaseWeak)( pWeak );
+
+ if (pHard)
+ {
+ (*pHard->dispose)( pHard ); // send explicit dispose
+ (*pHard->release)( pHard );
+ }
+ }
+}
+
+
+void EnvironmentsData::getEnvironment(
+ uno_Environment ** ppEnv, std::u16string_view rEnvDcp, void * pContext )
+{
+ if (*ppEnv)
+ {
+ (*(*ppEnv)->release)( *ppEnv );
+ *ppEnv = nullptr;
+ }
+
+ OUString aKey = OUString::number( reinterpret_cast< sal_IntPtr >(pContext) ) + rEnvDcp;
+
+ // try to find registered mapping
+ OUString2EnvironmentMap::const_iterator const iFind(
+ aName2EnvMap.find( aKey ) );
+ if (iFind != aName2EnvMap.end())
+ {
+ uno_Environment * pWeak = iFind->second;
+ (*pWeak->harden)( ppEnv, pWeak );
+ }
+}
+
+
+void EnvironmentsData::registerEnvironment( uno_Environment ** ppEnv )
+{
+ OSL_ENSURE( ppEnv, "### null ptr!" );
+ uno_Environment * pEnv = *ppEnv;
+
+ OUString aKey =
+ OUString::number( reinterpret_cast< sal_IntPtr >(pEnv->pContext) ) +
+ OUString::unacquired(&pEnv->pTypeName);
+
+ // try to find registered environment
+ OUString2EnvironmentMap::const_iterator const iFind(
+ aName2EnvMap.find( aKey ) );
+ if (iFind == aName2EnvMap.end())
+ {
+ (*pEnv->acquireWeak)( pEnv );
+ std::pair< OUString2EnvironmentMap::iterator, bool > insertion (
+ aName2EnvMap.emplace( aKey, pEnv ) );
+ SAL_WARN_IF( !insertion.second, "cppu", "key " << aKey << " already in env map" );
+ }
+ else
+ {
+ uno_Environment * pHard = nullptr;
+ uno_Environment * pWeak = iFind->second;
+ (*pWeak->harden)( &pHard, pWeak );
+ if (pHard)
+ {
+ (*pEnv->release)( pEnv );
+ *ppEnv = pHard;
+ }
+ else // registered one is dead
+ {
+ (*pWeak->releaseWeak)( pWeak );
+ (*pEnv->acquireWeak)( pEnv );
+ aName2EnvMap[ aKey ] = pEnv;
+ }
+ }
+}
+
+
+void EnvironmentsData::getRegisteredEnvironments(
+ uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc,
+ std::u16string_view rEnvDcp )
+{
+ assert(pppEnvs && pnLen && memAlloc && "### null ptr!");
+
+ // max size
+ std::vector<uno_Environment*> aFounds(aName2EnvMap.size());
+ sal_Int32 nSize = 0;
+
+ // find matching environment
+ for ( const auto& rEntry : aName2EnvMap )
+ {
+ uno_Environment * pWeak = rEntry.second;
+ if (rEnvDcp.empty() ||
+ rEnvDcp == OUString::unacquired(&pWeak->pTypeName) )
+ {
+ aFounds[nSize] = nullptr;
+ (*pWeak->harden)( &aFounds[nSize], pWeak );
+ if (aFounds[nSize])
+ ++nSize;
+ }
+ }
+
+ *pnLen = nSize;
+ if (nSize)
+ {
+ *pppEnvs = static_cast<uno_Environment **>((*memAlloc)(
+ sizeof (uno_Environment *) * nSize ));
+ OSL_ASSERT( *pppEnvs );
+ while (nSize--)
+ {
+ (*pppEnvs)[nSize] = aFounds[nSize];
+ }
+ }
+ else
+ {
+ *pppEnvs = nullptr;
+ }
+}
+
+bool loadEnv(OUString const & cLibStem,
+ uno_Environment * pEnv)
+{
+#ifdef DISABLE_DYNLOADING
+ uno_initEnvironmentFunc fpInit;
+
+ if ( cLibStem == CPPU_CURRENT_LANGUAGE_BINDING_NAME "_uno" )
+ fpInit = CPPU_ENV_uno_initEnvironment;
+#if HAVE_FEATURE_JAVA
+ else if ( cLibStem == "java_uno" )
+ fpInit = java_uno_initEnvironment;
+#endif
+ else
+ {
+ SAL_INFO("cppu", ": Unhandled env: " << cLibStem);
+ return false;
+ }
+#else
+ // late init with some code from matching uno language binding
+ // will be unloaded by environment
+ osl::Module aMod;
+ try {
+ bool bMod = cppu::detail::loadModule(aMod, cLibStem);
+ if (!bMod)
+ return false;
+ }
+ catch(...) {
+ // Catch everything and convert to return false
+ return false;
+ }
+
+
+ uno_initEnvironmentFunc fpInit = reinterpret_cast<uno_initEnvironmentFunc>(aMod.getSymbol(UNO_INIT_ENVIRONMENT));
+
+ if (!fpInit)
+ return false;
+
+ aMod.release();
+#endif
+
+ (*fpInit)( pEnv ); // init of environment
+ return true;
+}
+
+}
+
+extern "C"
+{
+
+
+static uno_Environment * initDefaultEnvironment(
+ const OUString & rEnvDcp, void * pContext )
+{
+ // coverity[leaked_storage : FALSE] - lifetime is controlled by acquire()/release() calls
+ uno_Environment * pEnv = &(new uno_DefaultEnvironment( rEnvDcp, pContext ))->aBase;
+ (*pEnv->acquire)( pEnv );
+
+ OUString envTypeName = cppu::EnvDcp::getTypeName(rEnvDcp);
+
+ // create default environment
+ if ( envTypeName == UNO_LB_UNO )
+ {
+ uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
+ that->computeObjectIdentifier = unoenv_computeObjectIdentifier;
+ that->acquireInterface = unoenv_acquireInterface;
+ that->releaseInterface = unoenv_releaseInterface;
+
+ OUString envPurpose = cppu::EnvDcp::getPurpose(rEnvDcp);
+ if (!envPurpose.isEmpty())
+ {
+ OUString libStem(
+ OUString::Concat(envPurpose.subView(envPurpose.lastIndexOf(':') + 1)) + "_uno_uno");
+ if(!loadEnv(libStem, pEnv))
+ {
+ pEnv->release(pEnv);
+ return nullptr;
+ }
+ }
+ }
+ else
+ {
+ // late init with some code from matching uno language binding
+ OUString aStr( envTypeName + "_uno" );
+
+ if (!loadEnv(aStr, pEnv))
+ {
+ pEnv->release(pEnv);
+ return nullptr;
+ }
+ }
+
+ return pEnv;
+}
+
+
+void SAL_CALL uno_createEnvironment(
+ uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext )
+ SAL_THROW_EXTERN_C()
+{
+ assert(ppEnv && "### null ptr!");
+ if (*ppEnv)
+ (*(*ppEnv)->release)( *ppEnv );
+
+ OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp );
+ *ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
+}
+
+void SAL_CALL uno_getEnvironment(
+ uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext )
+ SAL_THROW_EXTERN_C()
+{
+ assert(ppEnv && "### null ptr!");
+ OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp );
+
+ EnvironmentsData & rData = theEnvironmentsData();
+
+ ::osl::MutexGuard guard( rData.mutex );
+ rData.getEnvironment( ppEnv, rEnvDcp, pContext );
+ if (! *ppEnv)
+ {
+ *ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
+ if (*ppEnv)
+ {
+ // register new environment:
+ rData.registerEnvironment( ppEnv );
+ }
+ }
+}
+
+void SAL_CALL uno_getRegisteredEnvironments(
+ uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc,
+ rtl_uString * pEnvDcp )
+ SAL_THROW_EXTERN_C()
+{
+ EnvironmentsData & rData = theEnvironmentsData();
+
+ ::osl::MutexGuard guard( rData.mutex );
+ rData.getRegisteredEnvironments(
+ pppEnvs, pnLen, memAlloc,
+ (pEnvDcp ? OUString(pEnvDcp) : OUString()) );
+}
+
+} // extern "C"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/lbmap.cxx b/cppu/source/uno/lbmap.cxx
new file mode 100644
index 000000000..b056193de
--- /dev/null
+++ b/cppu/source/uno/lbmap.cxx
@@ -0,0 +1,754 @@
+/* -*- 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 .
+ */
+
+#ifdef DISABLE_DYNLOADING
+#include <config_java.h>
+#endif
+
+#include "IdentityMapping.hxx"
+
+#include <cassert>
+#include <mutex>
+#include <set>
+#include <unordered_map>
+#include <utility>
+
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <osl/module.hxx>
+#include <osl/diagnose.h>
+#include <osl/mutex.hxx>
+#include <osl/interlck.h>
+#include <sal/log.hxx>
+
+#include <uno/dispatcher.h>
+#include <uno/mapping.h>
+#include <uno/lbnames.h>
+#include <uno/environment.hxx>
+
+#include <typelib/typedescription.h>
+
+#include <cppu/EnvDcp.hxx>
+#include "cascade_mapping.hxx"
+#include "loadmodule.hxx"
+
+using namespace osl;
+using namespace com::sun::star::uno;
+
+namespace cppu
+{
+
+namespace {
+
+class Mapping
+{
+ uno_Mapping * _pMapping;
+
+public:
+ inline explicit Mapping( uno_Mapping * pMapping = nullptr );
+ inline Mapping( const Mapping & rMapping );
+ Mapping(Mapping && other) noexcept : _pMapping(other._pMapping)
+ { other._pMapping = nullptr; }
+ inline ~Mapping();
+ inline Mapping & operator = ( uno_Mapping * pMapping );
+ Mapping & operator = ( const Mapping & rMapping )
+ { return operator = ( rMapping._pMapping ); }
+ Mapping & operator =(Mapping && other) noexcept {
+ if (_pMapping != nullptr) {
+ (*_pMapping->release)(_pMapping);
+ }
+ _pMapping = other._pMapping;
+ other._pMapping = nullptr;
+ return *this;
+ }
+ uno_Mapping * get() const
+ { return _pMapping; }
+ bool is() const
+ { return (_pMapping != nullptr); }
+};
+
+}
+
+inline Mapping::Mapping( uno_Mapping * pMapping )
+ : _pMapping( pMapping )
+{
+ if (_pMapping)
+ (*_pMapping->acquire)( _pMapping );
+}
+
+inline Mapping::Mapping( const Mapping & rMapping )
+ : _pMapping( rMapping._pMapping )
+{
+ if (_pMapping)
+ (*_pMapping->acquire)( _pMapping );
+}
+
+inline Mapping::~Mapping()
+{
+ if (_pMapping)
+ (*_pMapping->release)( _pMapping );
+}
+
+inline Mapping & Mapping::operator = ( uno_Mapping * pMapping )
+{
+ if (pMapping)
+ (*pMapping->acquire)( pMapping );
+ if (_pMapping)
+ (*_pMapping->release)( _pMapping );
+ _pMapping = pMapping;
+ return *this;
+}
+
+namespace {
+
+struct MappingEntry
+{
+ sal_Int32 nRef;
+ uno_Mapping * pMapping;
+ uno_freeMappingFunc freeMapping;
+ OUString aMappingName;
+
+ MappingEntry(
+ uno_Mapping * pMapping_, uno_freeMappingFunc freeMapping_,
+ OUString aMappingName_ )
+ : nRef( 1 )
+ , pMapping( pMapping_ )
+ , freeMapping( freeMapping_ )
+ , aMappingName(std::move( aMappingName_ ))
+ {}
+};
+
+struct FctPtrHash
+{
+ size_t operator()( uno_Mapping * pKey ) const
+ { return reinterpret_cast<size_t>(pKey); }
+};
+
+}
+
+typedef std::unordered_map<
+ OUString, MappingEntry * > t_OUString2Entry;
+typedef std::unordered_map<
+ uno_Mapping *, MappingEntry *, FctPtrHash > t_Mapping2Entry;
+
+namespace {
+
+struct MappingsData
+{
+ Mutex aMappingsMutex;
+ t_OUString2Entry aName2Entry;
+ t_Mapping2Entry aMapping2Entry;
+
+ std::mutex aCallbacksMutex;
+ std::set< uno_getMappingFunc >
+ aCallbacks;
+
+ std::mutex aNegativeLibsMutex;
+ std::set<OUString> aNegativeLibs;
+};
+
+}
+
+static MappingsData & getMappingsData()
+{
+ //TODO This memory is leaked; see #i63473# for when this should be
+ // changed again:
+ static MappingsData * s_p(new MappingsData);
+
+ return *s_p;
+}
+
+namespace {
+
+/**
+ * This class mediates two different mapping via uno, e.g. form any language to uno,
+ * then from uno to any other language.
+ */
+struct uno_Mediate_Mapping : public uno_Mapping
+{
+ sal_Int32 nRef;
+
+ Environment aFrom;
+ Environment aTo;
+
+ Mapping aFrom2Uno;
+ Mapping aUno2To;
+
+ OUString aAddPurpose;
+
+ uno_Mediate_Mapping(
+ Environment aFrom_, Environment aTo_,
+ Mapping aFrom2Uno_, Mapping aUno2To_,
+ OUString aAddPurpose );
+};
+
+}
+
+extern "C"
+{
+
+static void mediate_free( uno_Mapping * pMapping )
+{
+ delete static_cast< uno_Mediate_Mapping * >( pMapping );
+}
+
+static void mediate_acquire( uno_Mapping * pMapping )
+{
+ if (1 == osl_atomic_increment(
+ & static_cast< uno_Mediate_Mapping * >( pMapping )->nRef ))
+ {
+ uno_registerMapping(
+ &pMapping, mediate_free,
+ static_cast< uno_Mediate_Mapping * >( pMapping )->aFrom.get(),
+ static_cast< uno_Mediate_Mapping * >( pMapping )->aTo.get(),
+ static_cast< uno_Mediate_Mapping * >( pMapping )->aAddPurpose.pData );
+ }
+}
+
+static void mediate_release( uno_Mapping * pMapping )
+{
+ if (! osl_atomic_decrement(
+ & static_cast< uno_Mediate_Mapping * >( pMapping )->nRef ))
+ {
+ uno_revokeMapping( pMapping );
+ }
+}
+
+static void mediate_mapInterface(
+ uno_Mapping * pMapping,
+ void ** ppOut, void * pInterface,
+ typelib_InterfaceTypeDescription * pInterfaceTypeDescr )
+{
+ OSL_ENSURE( pMapping && ppOut, "### null ptr!" );
+ if (!(pMapping && ppOut))
+ return;
+
+ uno_Mediate_Mapping * that = static_cast< uno_Mediate_Mapping * >( pMapping );
+ uno_Mapping * pFrom2Uno = that->aFrom2Uno.get();
+
+ uno_Interface * pUnoI = nullptr;
+ (*pFrom2Uno->mapInterface)( pFrom2Uno, reinterpret_cast<void **>(&pUnoI), pInterface, pInterfaceTypeDescr );
+ if (nullptr == pUnoI)
+ {
+ void * pOut = *ppOut;
+ if (nullptr != pOut)
+ {
+ uno_ExtEnvironment * pTo = that->aTo.get()->pExtEnv;
+ OSL_ENSURE( nullptr != pTo, "### cannot release out interface: leaking!" );
+ if (nullptr != pTo)
+ (*pTo->releaseInterface)( pTo, pOut );
+ *ppOut = nullptr; // set to 0 anyway, because mapping was not successful!
+ }
+ }
+ else
+ {
+ uno_Mapping * pUno2To = that->aUno2To.get();
+ (*pUno2To->mapInterface)( pUno2To, ppOut, pUnoI, pInterfaceTypeDescr );
+ (*pUnoI->release)( pUnoI );
+ }
+}
+}
+
+uno_Mediate_Mapping::uno_Mediate_Mapping(
+ Environment aFrom_, Environment aTo_,
+ Mapping aFrom2Uno_, Mapping aUno2To_,
+ OUString aAddPurpose_ )
+ : nRef( 1 )
+ , aFrom(std::move( aFrom_ ))
+ , aTo(std::move( aTo_ ))
+ , aFrom2Uno(std::move( aFrom2Uno_ ))
+ , aUno2To(std::move( aUno2To_ ))
+ , aAddPurpose(std::move( aAddPurpose_ ))
+{
+ uno_Mapping::acquire = mediate_acquire;
+ uno_Mapping::release = mediate_release;
+ uno_Mapping::mapInterface = mediate_mapInterface;
+}
+
+
+static OUString getMappingName(
+ const Environment & rFrom, const Environment & rTo, std::u16string_view rAddPurpose )
+{
+ OUStringBuffer aKey( 64 );
+ aKey.append( rAddPurpose );
+ aKey.append( ';' );
+ aKey.append( rFrom.getTypeName() );
+ aKey.append( '[' );
+ aKey.append( reinterpret_cast< sal_IntPtr >(rFrom.get()), 16 );
+ aKey.append( "];" );
+ aKey.append( rTo.getTypeName() );
+ aKey.append( '[' );
+ aKey.append( reinterpret_cast< sal_IntPtr >(rTo.get()), 16 );
+ aKey.append( ']' );
+ return aKey.makeStringAndClear();
+}
+
+static OUString getBridgeName(
+ const Environment & rFrom, const Environment & rTo, std::u16string_view rAddPurpose )
+{
+ OUStringBuffer aBridgeName( 16 );
+ if (!rAddPurpose.empty())
+ {
+ aBridgeName.append( rAddPurpose );
+ aBridgeName.append( '_' );
+ }
+ aBridgeName.append( EnvDcp::getTypeName(rFrom.getTypeName()) );
+ aBridgeName.append( '_' );
+ aBridgeName.append( EnvDcp::getTypeName(rTo.getTypeName()) );
+ return aBridgeName.makeStringAndClear();
+}
+
+#ifndef DISABLE_DYNLOADING
+
+static void setNegativeBridge( const OUString & rBridgeName )
+{
+ MappingsData & rData = getMappingsData();
+ std::scoped_lock aGuard( rData.aNegativeLibsMutex );
+ rData.aNegativeLibs.insert( rBridgeName );
+}
+
+#endif
+
+#ifdef DISABLE_DYNLOADING
+
+static uno_ext_getMappingFunc selectMapFunc( const OUString & rBridgeName )
+{
+ if (rBridgeName.equalsAscii( CPPU_CURRENT_LANGUAGE_BINDING_NAME "_uno" ))
+ return CPPU_ENV_uno_ext_getMapping;
+#if HAVE_FEATURE_JAVA
+ if (rBridgeName.equalsAscii( "java" "_uno" ))
+ return java_uno_ext_getMapping;
+#endif
+
+#if 0
+ // I don't think the affine or log bridges will be needed on any
+ // DISABLE_DYNLOADING platform (iOS at least, possibly Android), but if
+ // somebody wants to experiment, need to find out then whether these are
+ // needed.
+ if (rBridgeName.equalsAscii( "affine_uno_uno" ))
+ return affine_uno_uno_ext_getMapping;
+ if (rBridgeName.equalsAscii( "log_uno_uno" ))
+ return log_uno_uno_ext_getMapping;
+#endif
+ return 0;
+}
+
+#else
+
+static bool loadModule(osl::Module & rModule, const OUString & rBridgeName)
+{
+ bool bNeg;
+ {
+ MappingsData & rData = getMappingsData();
+ std::scoped_lock aGuard( rData.aNegativeLibsMutex );
+ const auto iFind( rData.aNegativeLibs.find( rBridgeName ) );
+ bNeg = (iFind != rData.aNegativeLibs.end());
+ }
+
+ if (!bNeg)
+ {
+ bool bModule;
+ try {
+ bModule = cppu::detail::loadModule(rModule, rBridgeName);
+ }
+ catch(...) {
+ // convert throw to return false
+ bModule = false;
+ }
+
+ if (bModule)
+ return true;
+
+ setNegativeBridge( rBridgeName ); // no load again
+ }
+ return false;
+}
+
+#endif
+
+
+static Mapping loadExternalMapping(
+ const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose )
+{
+ OSL_ASSERT( rFrom.is() && rTo.is() );
+ if (rFrom.is() && rTo.is())
+ {
+#ifdef DISABLE_DYNLOADING
+ OUString aName;
+ uno_ext_getMappingFunc fpGetMapFunc = 0;
+
+ if (EnvDcp::getTypeName(rFrom.getTypeName()) == UNO_LB_UNO)
+ {
+ aName = getBridgeName( rTo, rFrom, rAddPurpose );
+ fpGetMapFunc = selectMapFunc( aName );
+ }
+ if (! fpGetMapFunc)
+ {
+ aName = getBridgeName( rFrom, rTo, rAddPurpose );
+ fpGetMapFunc = selectMapFunc( aName );
+ }
+ if (! fpGetMapFunc)
+ {
+ aName = getBridgeName( rTo, rFrom, rAddPurpose );
+ fpGetMapFunc = selectMapFunc( aName );
+ }
+
+ if (! fpGetMapFunc)
+ {
+ SAL_INFO("cppu", "Could not find mapfunc for " << aName);
+ return Mapping();
+ }
+
+ if (fpGetMapFunc)
+ {
+ Mapping aExt;
+ (*fpGetMapFunc)( (uno_Mapping **)&aExt, rFrom.get(), rTo.get() );
+ OSL_ASSERT( aExt.is() );
+ if (aExt.is())
+ return aExt;
+ SAL_INFO("cppu", "Could not load external mapping for " << aName);
+ }
+#else
+ // find proper lib
+ osl::Module aModule;
+ bool bModule(false);
+ OUString aName;
+
+ if ( EnvDcp::getTypeName(rFrom.getTypeName()) == UNO_LB_UNO )
+ {
+ aName = getBridgeName( rTo, rFrom, rAddPurpose );
+ bModule = loadModule( aModule, aName );
+ }
+ if (!bModule)
+ {
+ aName = getBridgeName( rFrom, rTo, rAddPurpose );
+ bModule = loadModule( aModule, aName );
+ }
+ if (!bModule)
+ {
+ aName = getBridgeName( rTo, rFrom, rAddPurpose );
+ bModule = loadModule( aModule, aName );
+ }
+
+ if (bModule)
+ {
+ uno_ext_getMappingFunc fpGetMapFunc =
+ reinterpret_cast<uno_ext_getMappingFunc>(aModule.getSymbol( UNO_EXT_GETMAPPING ));
+
+ if (fpGetMapFunc)
+ {
+ Mapping aExt;
+ (*fpGetMapFunc)( reinterpret_cast<uno_Mapping **>(&aExt), rFrom.get(), rTo.get() );
+ OSL_ASSERT( aExt.is() );
+ if (aExt.is())
+ {
+ aModule.release();
+ return aExt;
+ }
+ }
+ aModule.unload();
+ setNegativeBridge( aName );
+ }
+#endif
+ }
+ return Mapping();
+}
+
+
+static Mapping getDirectMapping(
+ const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose = OUString() )
+
+{
+ OSL_ASSERT( rFrom.is() && rTo.is() );
+ if (rFrom.is() && rTo.is())
+ {
+ MappingsData & rData = getMappingsData();
+ ClearableMutexGuard aGuard( rData.aMappingsMutex );
+
+ // try to find registered mapping
+ const t_OUString2Entry::const_iterator iFind( rData.aName2Entry.find(
+ getMappingName( rFrom, rTo, rAddPurpose ) ) );
+
+ if (iFind == rData.aName2Entry.end())
+ {
+ aGuard.clear();
+ return loadExternalMapping( rFrom, rTo, rAddPurpose );
+ }
+ return Mapping( (*iFind).second->pMapping );
+ }
+ return Mapping();
+}
+
+
+static Mapping createMediateMapping(
+ const Environment & rFrom, const Environment & rTo,
+ const Mapping & rFrom2Uno, const Mapping & rUno2To,
+ const OUString & rAddPurpose )
+{
+ uno_Mapping * pRet = new uno_Mediate_Mapping(
+ rFrom, rTo, rFrom2Uno, rUno2To, rAddPurpose ); // ref count initially 1
+ uno_registerMapping(
+ &pRet, mediate_free, rFrom.get(), rTo.get(), rAddPurpose.pData );
+ Mapping aRet( pRet );
+ (*pRet->release)( pRet );
+ return aRet;
+}
+
+static Mapping getMediateMapping(
+ const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose )
+{
+ Environment aUno;
+ Mapping aUno2To;
+
+ // backwards: from dest to source of mapping chain
+
+ // connect to uno
+ OUString aUnoEnvTypeName( UNO_LB_UNO );
+ if (rTo.getTypeName() == aUnoEnvTypeName) // to is uno
+ {
+ aUno = rTo;
+ // no Uno2To mapping necessary
+ }
+ else
+ {
+ // get registered uno env
+ ::uno_getEnvironment( reinterpret_cast<uno_Environment **>(&aUno), aUnoEnvTypeName.pData, nullptr );
+
+ aUno2To = getDirectMapping( aUno, rTo );
+ // : uno <-> to
+ if (! aUno2To.is())
+ return Mapping();
+ }
+
+ // connect to uno
+ if (!rAddPurpose.isEmpty()) // insert purpose mapping between new ano_uno <-> uno
+ {
+ // create anonymous uno env
+ Environment aAnUno;
+ ::uno_createEnvironment( reinterpret_cast<uno_Environment **>(&aAnUno), aUnoEnvTypeName.pData, nullptr );
+
+ Mapping aAnUno2Uno( getDirectMapping( aAnUno, aUno, rAddPurpose ) );
+ if (! aAnUno2Uno.is())
+ return Mapping();
+
+ if (aUno2To.is()) // to is not uno
+ {
+ // create another purposed mediate mapping
+ aUno2To = createMediateMapping( aAnUno, rTo, aAnUno2Uno, aUno2To, rAddPurpose );
+ // : ano_uno <-> uno <-> to
+ }
+ else
+ {
+ aUno2To = aAnUno2Uno;
+ // : ano_uno <-> to (i.e., uno)
+ }
+ aUno = aAnUno;
+ }
+
+ Mapping aFrom2Uno( getDirectMapping( rFrom, aUno ) );
+ if (aFrom2Uno.is() && aUno2To.is())
+ {
+ return createMediateMapping( rFrom, rTo, aFrom2Uno, aUno2To, rAddPurpose );
+ // : from <-> some uno ...
+ }
+
+ return Mapping();
+}
+}
+
+using namespace ::cppu;
+
+extern "C"
+{
+
+void SAL_CALL uno_getMapping(
+ uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo,
+ rtl_uString * pAddPurpose )
+ SAL_THROW_EXTERN_C()
+{
+ assert(ppMapping != nullptr);
+ assert(pFrom != nullptr);
+ assert(pTo != nullptr);
+ if (*ppMapping)
+ {
+ (*(*ppMapping)->release)( *ppMapping );
+ *ppMapping = nullptr;
+ }
+
+ Mapping aRet;
+ Environment aFrom( pFrom ), aTo( pTo );
+
+ OUString aAddPurpose;
+ if (pAddPurpose)
+ aAddPurpose = pAddPurpose;
+
+ MappingsData & rData = getMappingsData();
+
+ // try registered mapping
+ {
+ MutexGuard aGuard( rData.aMappingsMutex );
+ const t_OUString2Entry::const_iterator iFind( rData.aName2Entry.find(
+ getMappingName( aFrom, aTo, aAddPurpose ) ) );
+ if (iFind != rData.aName2Entry.end())
+ aRet = (*iFind).second->pMapping;
+ }
+
+ // See if an identity mapping does fit.
+ if (!aRet.is() && pFrom == pTo && aAddPurpose.isEmpty())
+ aRet = createIdentityMapping(pFrom);
+
+ if (!aRet.is())
+ {
+ getCascadeMapping(ppMapping, pFrom, pTo, pAddPurpose);
+
+ if (*ppMapping)
+ return;
+
+ // try callback chain
+ {
+ std::unique_lock aGuard(rData.aCallbacksMutex);
+ for (const auto& rCallback : rData.aCallbacks)
+ {
+ (*rCallback)(ppMapping, pFrom, pTo, aAddPurpose.pData);
+ if (*ppMapping)
+ return;
+ }
+ }
+
+ aRet = loadExternalMapping( aFrom, aTo, aAddPurpose ); // direct try
+ if (! aRet.is())
+ aRet = getMediateMapping( aFrom, aTo, aAddPurpose ); // try via uno
+ }
+
+ if (aRet.is())
+ {
+ (*aRet.get()->acquire)( aRet.get() );
+ *ppMapping = aRet.get();
+ }
+}
+
+void SAL_CALL uno_getMappingByName(
+ uno_Mapping ** ppMapping, rtl_uString * pFrom, rtl_uString * pTo,
+ rtl_uString * pAddPurpose )
+ SAL_THROW_EXTERN_C()
+{
+ assert(ppMapping && pFrom && pTo && "### null ptr!");
+ if (*ppMapping)
+ {
+ (*(*ppMapping)->release)( *ppMapping );
+ *ppMapping = nullptr;
+ }
+
+ uno_Environment * pEFrom = nullptr;
+ uno_getEnvironment( &pEFrom, pFrom, nullptr );
+ OSL_ENSURE( pEFrom, "### cannot get source environment!" );
+ if (pEFrom)
+ {
+ uno_Environment * pETo = nullptr;
+ uno_getEnvironment( &pETo, pTo, nullptr );
+ OSL_ENSURE( pETo, "### cannot get target environment!" );
+ if (pETo)
+ {
+ ::uno_getMapping( ppMapping, pEFrom, pETo, pAddPurpose );
+ (*pETo->release)( pETo );
+ }
+ (*pEFrom->release)( pEFrom );
+ }
+}
+
+
+void SAL_CALL uno_registerMapping(
+ uno_Mapping ** ppMapping, uno_freeMappingFunc freeMapping,
+ uno_Environment * pFrom, uno_Environment * pTo, rtl_uString * pAddPurpose )
+ SAL_THROW_EXTERN_C()
+{
+ MappingsData & rData = getMappingsData();
+ ClearableMutexGuard aGuard( rData.aMappingsMutex );
+
+ const t_Mapping2Entry::const_iterator iFind( rData.aMapping2Entry.find( *ppMapping ) );
+ if (iFind == rData.aMapping2Entry.end())
+ {
+ OUString aMappingName(
+ getMappingName( pFrom, pTo, pAddPurpose ? OUString(pAddPurpose) : OUString() ) );
+ SAL_INFO("cppu", "> inserting new mapping: " << aMappingName);
+ // count initially 1
+ MappingEntry * pEntry = new MappingEntry( *ppMapping, freeMapping, aMappingName );
+ rData.aName2Entry[ aMappingName ] = pEntry;
+ rData.aMapping2Entry[ *ppMapping ] = pEntry;
+ }
+ else
+ {
+ MappingEntry * pEntry = (*iFind).second;
+ ++pEntry->nRef;
+
+ if (pEntry->pMapping != *ppMapping) // exchange mapping to be registered
+ {
+ (*pEntry->pMapping->acquire)( pEntry->pMapping );
+ --pEntry->nRef; // correct count; kill mapping to be registered
+ aGuard.clear();
+ (*freeMapping)( *ppMapping );
+ *ppMapping = pEntry->pMapping;
+ }
+ }
+}
+
+void SAL_CALL uno_revokeMapping(
+ uno_Mapping * pMapping )
+ SAL_THROW_EXTERN_C()
+{
+ MappingsData & rData = getMappingsData();
+ ClearableMutexGuard aGuard( rData.aMappingsMutex );
+
+ const t_Mapping2Entry::const_iterator iFind( rData.aMapping2Entry.find( pMapping ) );
+ OSL_ASSERT( iFind != rData.aMapping2Entry.end() );
+ MappingEntry * pEntry = (*iFind).second;
+ if (! --pEntry->nRef)
+ {
+ rData.aMapping2Entry.erase( pEntry->pMapping );
+ rData.aName2Entry.erase( pEntry->aMappingName );
+ aGuard.clear();
+ SAL_INFO("cppu", "> revoking mapping " << pEntry->aMappingName);
+ (*pEntry->freeMapping)( pEntry->pMapping );
+ delete pEntry;
+ }
+}
+
+
+void SAL_CALL uno_registerMappingCallback(
+ uno_getMappingFunc pCallback )
+ SAL_THROW_EXTERN_C()
+{
+ OSL_ENSURE( pCallback, "### null ptr!" );
+ MappingsData & rData = getMappingsData();
+ std::unique_lock aGuard( rData.aCallbacksMutex );
+ rData.aCallbacks.insert( pCallback );
+}
+
+void SAL_CALL uno_revokeMappingCallback(
+ uno_getMappingFunc pCallback )
+ SAL_THROW_EXTERN_C()
+{
+ OSL_ENSURE( pCallback, "### null ptr!" );
+ MappingsData & rData = getMappingsData();
+ std::unique_lock aGuard( rData.aCallbacksMutex );
+ rData.aCallbacks.erase( pCallback );
+}
+} // extern "C"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/loadmodule.cxx b/cppu/source/uno/loadmodule.cxx
new file mode 100644
index 000000000..f2811a595
--- /dev/null
+++ b/cppu/source/uno/loadmodule.cxx
@@ -0,0 +1,75 @@
+/* -*- 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 <cassert>
+
+#include <osl/module.h>
+#include <osl/module.hxx>
+#include <rtl/malformeduriexception.hxx>
+#include <rtl/uri.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+
+#include "loadmodule.hxx"
+
+namespace cppu::detail {
+
+#ifndef DISABLE_DYNLOADING
+
+bool loadModule(osl::Module& rModule, OUString const & name) {
+ static OUString base = [] {
+ OUString url;
+ if (!osl::Module::getUrlFromAddress(
+ reinterpret_cast<oslGenericFunction>(&loadModule), url))
+ {
+ SAL_WARN("cppu", "osl::Module::getUrlFromAddress failed");
+ return OUString();
+ }
+ assert(!url.isEmpty());
+ return url;
+ }();
+ if (base.isEmpty()) {
+ SAL_INFO("cppu", "osl::Module::getUrlFromAddress had failed");
+ return false;
+ }
+ OUString b =
+#if defined SAL_DLLPREFIX
+ SAL_DLLPREFIX +
+#endif
+ name +
+ SAL_DLLEXTENSION;
+ try {
+ b = rtl::Uri::convertRelToAbs(base, b);
+ } catch (rtl::MalformedUriException & e) {
+ SAL_INFO("cppu", "rtl::MalformedUriException <" << e.getMessage() << ">");
+ return false;
+ }
+ return rModule.load(
+ b,
+ SAL_LOADMODULE_GLOBAL | SAL_LOADMODULE_LAZY);
+}
+
+#endif
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/loadmodule.hxx b/cppu/source/uno/loadmodule.hxx
new file mode 100644
index 000000000..694b14024
--- /dev/null
+++ b/cppu/source/uno/loadmodule.hxx
@@ -0,0 +1,47 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+#include <rtl/ustring.hxx>
+
+namespace osl
+{
+class Module;
+}
+
+namespace cppu::detail
+{
+#ifndef DISABLE_DYNLOADING
+
+/** Load a module.
+
+ @param name
+ the nucleus of a module name (without any "lib...so", ".dll", etc.
+ decoration, and without a path).
+
+ @return false if the module could not be loaded, otherwise true
+*/
+bool loadModule(osl::Module& rModule, OUString const& name);
+
+#endif
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/prim.hxx b/cppu/source/uno/prim.hxx
new file mode 100644
index 000000000..733baec0f
--- /dev/null
+++ b/cppu/source/uno/prim.hxx
@@ -0,0 +1,153 @@
+/* -*- 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 .
+ */
+#pragma once
+
+#include <typelib/typedescription.h>
+#include <typelib/typeclass.h>
+#include <uno/sequence2.h>
+#include <uno/any2.h>
+#include <uno/data.h>
+#include <uno/mapping.h>
+#include <uno/dispatcher.h>
+
+#include <osl/interlck.h>
+#include <stdint.h>
+
+namespace cppu
+{
+
+extern uno_Sequence g_emptySeq;
+extern typelib_TypeDescriptionReference * g_pVoidType;
+
+
+inline void * _map(
+ void * p,
+ typelib_TypeDescriptionReference * pType, typelib_TypeDescription * pTypeDescr,
+ uno_Mapping * mapping )
+
+{
+ void * pRet = nullptr;
+ if (p)
+ {
+ if (pTypeDescr)
+ {
+ (*mapping->mapInterface)(
+ mapping, &pRet, p, reinterpret_cast<typelib_InterfaceTypeDescription *>(pTypeDescr) );
+ }
+ else
+ {
+ TYPELIB_DANGER_GET( &pTypeDescr, pType );
+ (*mapping->mapInterface)(
+ mapping, &pRet, p, reinterpret_cast<typelib_InterfaceTypeDescription *>(pTypeDescr) );
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ }
+ }
+ return pRet;
+}
+
+inline void _acquire( void * p, uno_AcquireFunc acquire )
+{
+ if (p)
+ {
+ if (acquire)
+ {
+ (*acquire)( p );
+ }
+ else
+ {
+ (*static_cast<uno_Interface *>(p)->acquire)( static_cast<uno_Interface *>(p) );
+ }
+ }
+}
+
+inline void _release( void * p, uno_ReleaseFunc release )
+{
+ if (p)
+ {
+ if (release)
+ {
+ (*release)( p );
+ }
+ else
+ {
+ (*static_cast<uno_Interface *>(p)->release)( static_cast<uno_Interface *>(p) );
+ }
+ }
+}
+
+
+inline sal_uInt32 calcSeqMemSize(
+ sal_Int32 nElementSize, sal_Int32 nElements )
+{
+ sal_uInt64 nSize =
+ static_cast<sal_uInt64>(SAL_SEQUENCE_HEADER_SIZE) +
+ (static_cast<sal_uInt64>(nElementSize) * static_cast<sal_uInt64>(nElements));
+ if (nSize > 0xffffffffU)
+ return 0;
+ else
+ return static_cast<sal_uInt32>(nSize);
+}
+
+
+inline uno_Sequence * createEmptySequence()
+{
+ osl_atomic_increment( &g_emptySeq.nRefCount );
+ return &g_emptySeq;
+}
+
+inline typelib_TypeDescriptionReference * _getVoidType()
+{
+ if (! g_pVoidType)
+ {
+ g_pVoidType = * ::typelib_static_type_getByTypeClass( typelib_TypeClass_VOID );
+ }
+ ::typelib_typedescriptionreference_acquire( g_pVoidType );
+ return g_pVoidType;
+}
+
+inline void CONSTRUCT_EMPTY_ANY(uno_Any * pAny) {
+ pAny->pType = _getVoidType();
+#if OSL_DEBUG_LEVEL > 0
+ pAny->pData = reinterpret_cast<void *>(uintptr_t(0xdeadbeef));
+#else
+ pAny->pData = pAny;
+#endif
+}
+
+#define TYPE_ACQUIRE( pType ) \
+ osl_atomic_increment( &(pType)->nRefCount );
+
+
+extern "C" void * binuno_queryInterface(
+ void * pUnoI, typelib_TypeDescriptionReference * pDestType );
+
+
+inline bool _type_equals(
+ typelib_TypeDescriptionReference const * pType1, typelib_TypeDescriptionReference const * pType2 )
+
+{
+ return (pType1 == pType2 ||
+ (pType1->eTypeClass == pType2->eTypeClass &&
+ pType1->pTypeName->length == pType2->pTypeName->length &&
+ ::rtl_ustr_compare( pType1->pTypeName->buffer, pType2->pTypeName->buffer ) == 0));
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/source/uno/sequence.cxx b/cppu/source/uno/sequence.cxx
new file mode 100644
index 000000000..c467f2c38
--- /dev/null
+++ b/cppu/source/uno/sequence.cxx
@@ -0,0 +1,912 @@
+/* -*- 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 <cassert>
+#include <string.h>
+
+#include <osl/diagnose.h>
+#include <osl/interlck.h>
+#include <typelib/typedescription.h>
+#include <uno/data.h>
+#include <uno/sequence2.h>
+
+#include "constr.hxx"
+#include "copy.hxx"
+#include "destr.hxx"
+
+
+using namespace cppu;
+
+namespace cppu
+{
+
+
+static uno_Sequence * reallocSeq(
+ uno_Sequence * pReallocate, std::size_t nElementSize, sal_Int32 nElements )
+{
+ OSL_ASSERT( nElements >= 0 );
+ uno_Sequence * pNew = nullptr;
+ sal_uInt32 nSize = calcSeqMemSize( nElementSize, nElements );
+ if (nSize > 0)
+ {
+ if (pReallocate == nullptr)
+ {
+ pNew = static_cast<uno_Sequence *>(std::malloc( nSize ));
+ }
+ else
+ {
+ pNew = static_cast<uno_Sequence *>(std::realloc( pReallocate, nSize ));
+ }
+ if (pNew != nullptr)
+ {
+ // header init
+ pNew->nRefCount = 1;
+ pNew->nElements = nElements;
+ }
+ }
+ return pNew;
+}
+
+
+static bool idefaultConstructElements(
+ uno_Sequence ** ppSeq,
+ typelib_TypeDescriptionReference * pElementType,
+ sal_Int32 nStartIndex, sal_Int32 nStopIndex,
+ sal_Int32 nAlloc ) // >= 0 means (re)alloc memory for nAlloc elements
+{
+ uno_Sequence * pSeq = *ppSeq;
+ switch (pElementType->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ if (nAlloc >= 0)
+ pSeq = reallocSeq( pSeq, sizeof(sal_Unicode), nAlloc );
+ if (pSeq != nullptr)
+ {
+ memset(
+ pSeq->elements + (sizeof(sal_Unicode) * nStartIndex),
+ 0,
+ sizeof(sal_Unicode) * (nStopIndex - nStartIndex) );
+ }
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ if (nAlloc >= 0)
+ pSeq = reallocSeq( pSeq, sizeof(sal_Bool), nAlloc );
+ if (pSeq != nullptr)
+ {
+ memset(
+ pSeq->elements + (sizeof(sal_Bool) * nStartIndex),
+ 0,
+ sizeof(sal_Bool) * (nStopIndex - nStartIndex) );
+ }
+ break;
+ case typelib_TypeClass_BYTE:
+ if (nAlloc >= 0)
+ pSeq = reallocSeq( pSeq, sizeof(sal_Int8), nAlloc );
+ if (pSeq != nullptr)
+ {
+ memset(
+ pSeq->elements + (sizeof(sal_Int8) * nStartIndex),
+ 0,
+ sizeof(sal_Int8) * (nStopIndex - nStartIndex) );
+ }
+ break;
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ if (nAlloc >= 0)
+ pSeq = reallocSeq( pSeq, sizeof(sal_Int16), nAlloc );
+ if (pSeq != nullptr)
+ {
+ memset(
+ pSeq->elements + (sizeof(sal_Int16) * nStartIndex),
+ 0,
+ sizeof(sal_Int16) * (nStopIndex - nStartIndex) );
+ }
+ break;
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ if (nAlloc >= 0)
+ pSeq = reallocSeq( pSeq, sizeof(sal_Int32), nAlloc );
+ if (pSeq != nullptr)
+ {
+ memset(
+ pSeq->elements + (sizeof(sal_Int32) * nStartIndex),
+ 0,
+ sizeof(sal_Int32) * (nStopIndex - nStartIndex) );
+ }
+ break;
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ if (nAlloc >= 0)
+ pSeq = reallocSeq( pSeq, sizeof(sal_Int64), nAlloc );
+ if (pSeq != nullptr)
+ {
+ memset(
+ pSeq->elements + (sizeof(sal_Int64) * nStartIndex),
+ 0,
+ sizeof(sal_Int64) * (nStopIndex - nStartIndex) );
+ }
+ break;
+ case typelib_TypeClass_FLOAT:
+ {
+ if (nAlloc >= 0)
+ pSeq = reallocSeq( pSeq, sizeof(float), nAlloc );
+ if (pSeq != nullptr)
+ {
+ float * pElements = reinterpret_cast<float *>(pSeq->elements);
+ for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
+ {
+ pElements[nPos] = 0.0;
+ }
+ }
+ break;
+ }
+ case typelib_TypeClass_DOUBLE:
+ {
+ if (nAlloc >= 0)
+ pSeq = reallocSeq( pSeq, sizeof(double), nAlloc );
+ if (pSeq != nullptr)
+ {
+ double * pElements = reinterpret_cast<double *>(pSeq->elements);
+ for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
+ {
+ pElements[nPos] = 0.0;
+ }
+ }
+ break;
+ }
+ case typelib_TypeClass_STRING:
+ {
+ if (nAlloc >= 0)
+ pSeq = reallocSeq( pSeq, sizeof(rtl_uString *), nAlloc );
+ if (pSeq != nullptr)
+ {
+ rtl_uString ** pElements = reinterpret_cast<rtl_uString **>(pSeq->elements);
+ for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
+ {
+ pElements[nPos] = nullptr;
+ rtl_uString_new( &pElements[nPos] );
+ }
+ }
+ break;
+ }
+ case typelib_TypeClass_TYPE:
+ {
+ if (nAlloc >= 0)
+ {
+ pSeq = reallocSeq(
+ pSeq, sizeof(typelib_TypeDescriptionReference *), nAlloc );
+ }
+ if (pSeq != nullptr)
+ {
+ typelib_TypeDescriptionReference ** pElements =
+ reinterpret_cast<typelib_TypeDescriptionReference **>(pSeq->elements);
+ for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
+ {
+ pElements[nPos] = _getVoidType();
+ }
+ }
+ break;
+ }
+ case typelib_TypeClass_ANY:
+ {
+ if (nAlloc >= 0)
+ pSeq = reallocSeq( pSeq, sizeof(uno_Any), nAlloc );
+ if (pSeq != nullptr)
+ {
+ uno_Any * pElements = reinterpret_cast<uno_Any *>(pSeq->elements);
+ for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
+ {
+ CONSTRUCT_EMPTY_ANY( &pElements[nPos] );
+ }
+ }
+ break;
+ }
+ case typelib_TypeClass_ENUM:
+ {
+ if (nAlloc >= 0)
+ pSeq = reallocSeq( pSeq, sizeof(sal_Int32), nAlloc );
+ if (pSeq != nullptr)
+ {
+ typelib_TypeDescription * pElementTypeDescr = nullptr;
+ TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
+ sal_Int32 eEnum =
+ reinterpret_cast<typelib_EnumTypeDescription *>(
+ pElementTypeDescr)->nDefaultEnumValue;
+ TYPELIB_DANGER_RELEASE( pElementTypeDescr );
+
+ sal_Int32 * pElements = reinterpret_cast<sal_Int32 *>(pSeq->elements);
+ for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
+ {
+ pElements[nPos] = eEnum;
+ }
+ }
+ break;
+ }
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ typelib_TypeDescription * pElementTypeDescr = nullptr;
+ TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
+ sal_Int32 nElementSize = pElementTypeDescr->nSize;
+
+ if (nAlloc >= 0)
+ pSeq = reallocSeq( pSeq, nElementSize, nAlloc );
+ if (pSeq != nullptr)
+ {
+ char * pElements = pSeq->elements;
+ for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
+ {
+ _defaultConstructStruct(
+ pElements + (nElementSize * nPos),
+ reinterpret_cast<typelib_CompoundTypeDescription *>(pElementTypeDescr) );
+ }
+ }
+
+ TYPELIB_DANGER_RELEASE( pElementTypeDescr );
+ break;
+ }
+ case typelib_TypeClass_SEQUENCE:
+ {
+ if (nAlloc >= 0)
+ {
+ // coverity[suspicious_sizeof : FALSE] - sizeof(uno_Sequence*) is correct here
+ pSeq = reallocSeq(pSeq, sizeof(uno_Sequence*), nAlloc);
+ }
+ if (pSeq != nullptr)
+ {
+ uno_Sequence ** pElements =
+ reinterpret_cast<uno_Sequence **>(pSeq->elements);
+ for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
+ {
+ pElements[nPos] = createEmptySequence();
+ }
+ }
+ break;
+ }
+ case typelib_TypeClass_INTERFACE: // either C++ or C-UNO interface
+ if (nAlloc >= 0)
+ pSeq = reallocSeq( pSeq, sizeof(void *), nAlloc );
+ if (pSeq != nullptr)
+ {
+ memset(
+ pSeq->elements + (sizeof(void *) * nStartIndex),
+ 0,
+ sizeof(void *) * (nStopIndex - nStartIndex) );
+ }
+ break;
+ default:
+ OSL_FAIL( "### unexpected element type!" );
+ pSeq = nullptr;
+ break;
+ }
+
+ if (pSeq == nullptr)
+ {
+ OSL_ASSERT( nAlloc >= 0 ); // must have been an allocation failure
+ return false;
+ }
+ *ppSeq = pSeq;
+ return true;
+}
+
+// coverity[ -tainted_data_sink : arg-1 ]
+static bool icopyConstructFromElements(
+ uno_Sequence ** ppSeq, void * pSourceElements,
+ typelib_TypeDescriptionReference * pElementType,
+ sal_Int32 nStopIndex,
+ uno_AcquireFunc acquire,
+ sal_Int32 nAlloc )
+{
+ uno_Sequence * pSeq = *ppSeq;
+ switch (pElementType->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ pSeq = reallocSeq( pSeq, sizeof(sal_Unicode), nAlloc );
+ if (pSeq != nullptr)
+ {
+ memcpy(
+ pSeq->elements,
+ pSourceElements,
+ sizeof(sal_Unicode) * nStopIndex );
+ }
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ pSeq = reallocSeq( pSeq, sizeof(sal_Bool), nAlloc );
+ if (pSeq != nullptr)
+ {
+ memcpy(
+ pSeq->elements,
+ pSourceElements,
+ sizeof(sal_Bool) * nStopIndex );
+ }
+ break;
+ case typelib_TypeClass_BYTE:
+ pSeq = reallocSeq( pSeq, sizeof(sal_Int8), nAlloc );
+ if (pSeq != nullptr)
+ {
+ memcpy(
+ pSeq->elements,
+ pSourceElements,
+ sizeof(sal_Int8) * nStopIndex );
+ }
+ break;
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ pSeq = reallocSeq( pSeq, sizeof(sal_Int16), nAlloc );
+ if (pSeq != nullptr)
+ {
+ memcpy(
+ pSeq->elements,
+ pSourceElements,
+ sizeof(sal_Int16) * nStopIndex );
+ }
+ break;
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ pSeq = reallocSeq( pSeq, sizeof(sal_Int32), nAlloc );
+ if (pSeq != nullptr)
+ {
+ memcpy(
+ pSeq->elements,
+ pSourceElements,
+ sizeof(sal_Int32) * nStopIndex );
+ }
+ break;
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ pSeq = reallocSeq( pSeq, sizeof(sal_Int64), nAlloc );
+ if (pSeq != nullptr)
+ {
+ memcpy(
+ pSeq->elements,
+ pSourceElements,
+ sizeof(sal_Int64) * nStopIndex );
+ }
+ break;
+ case typelib_TypeClass_FLOAT:
+ pSeq = reallocSeq( pSeq, sizeof(float), nAlloc );
+ if (pSeq != nullptr)
+ {
+ memcpy(
+ pSeq->elements,
+ pSourceElements,
+ sizeof(float) * nStopIndex );
+ }
+ break;
+ case typelib_TypeClass_DOUBLE:
+ pSeq = reallocSeq( pSeq, sizeof(double), nAlloc );
+ if (pSeq != nullptr)
+ {
+ memcpy(
+ pSeq->elements,
+ pSourceElements,
+ sizeof(double) * nStopIndex );
+ }
+ break;
+ case typelib_TypeClass_ENUM:
+ pSeq = reallocSeq( pSeq, sizeof(sal_Int32), nAlloc );
+ if (pSeq != nullptr)
+ {
+ memcpy(
+ pSeq->elements,
+ pSourceElements,
+ sizeof(sal_Int32) * nStopIndex );
+ }
+ break;
+ case typelib_TypeClass_STRING:
+ {
+ pSeq = reallocSeq( pSeq, sizeof(rtl_uString *), nAlloc );
+ if (pSeq != nullptr)
+ {
+ rtl_uString ** pDestElements = reinterpret_cast<rtl_uString **>(pSeq->elements);
+ for ( sal_Int32 nPos = 0; nPos < nStopIndex; ++nPos )
+ {
+ // This code tends to trigger coverity's overrun-buffer-arg warning
+ // coverity[index_parm_via_loop_bound] - https://communities.coverity.com/thread/2993
+ ::rtl_uString_acquire(
+ static_cast<rtl_uString **>(pSourceElements)[nPos] );
+ pDestElements[nPos] = static_cast<rtl_uString **>(pSourceElements)[nPos];
+ }
+ }
+ break;
+ }
+ case typelib_TypeClass_TYPE:
+ {
+ pSeq = reallocSeq(
+ pSeq, sizeof(typelib_TypeDescriptionReference *), nAlloc );
+ if (pSeq != nullptr)
+ {
+ typelib_TypeDescriptionReference ** pDestElements =
+ reinterpret_cast<typelib_TypeDescriptionReference **>(pSeq->elements);
+ for ( sal_Int32 nPos = 0; nPos < nStopIndex; ++nPos )
+ {
+ TYPE_ACQUIRE(
+ static_cast<typelib_TypeDescriptionReference **>(
+ pSourceElements)[nPos] );
+ pDestElements[nPos] =
+ static_cast<typelib_TypeDescriptionReference **>(
+ pSourceElements)[nPos];
+ }
+ }
+ break;
+ }
+ case typelib_TypeClass_ANY:
+ {
+ pSeq = reallocSeq( pSeq, sizeof(uno_Any), nAlloc );
+ if (pSeq != nullptr)
+ {
+ uno_Any * pDestElements = reinterpret_cast<uno_Any *>(pSeq->elements);
+ for ( sal_Int32 nPos = 0; nPos < nStopIndex; ++nPos )
+ {
+ uno_Any * pSource = static_cast<uno_Any *>(pSourceElements) + nPos;
+ _copyConstructAny(
+ &pDestElements[nPos],
+ pSource->pData,
+ pSource->pType, nullptr,
+ acquire, nullptr );
+ }
+ }
+ break;
+ }
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ typelib_TypeDescription * pElementTypeDescr = nullptr;
+ TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
+ sal_Int32 nElementSize = pElementTypeDescr->nSize;
+
+ pSeq = reallocSeq( pSeq, nElementSize, nAlloc );
+ if (pSeq != nullptr)
+ {
+ char * pDestElements = pSeq->elements;
+
+ typelib_CompoundTypeDescription * pTypeDescr =
+ reinterpret_cast<typelib_CompoundTypeDescription *>(pElementTypeDescr);
+ for ( sal_Int32 nPos = 0; nPos < nStopIndex; ++nPos )
+ {
+ char * pDest =
+ pDestElements + (nElementSize * nPos);
+ char * pSource =
+ static_cast<char *>(pSourceElements) + (nElementSize * nPos);
+
+ if (pTypeDescr->pBaseTypeDescription)
+ {
+ // copy base value
+ _copyConstructStruct(
+ pDest, pSource,
+ pTypeDescr->pBaseTypeDescription, acquire, nullptr );
+ }
+
+ // then copy members
+ typelib_TypeDescriptionReference ** ppTypeRefs =
+ pTypeDescr->ppTypeRefs;
+ sal_Int32 * pMemberOffsets = pTypeDescr->pMemberOffsets;
+ sal_Int32 nDescr = pTypeDescr->nMembers;
+
+ while (nDescr--)
+ {
+ ::uno_type_copyData(
+ pDest + pMemberOffsets[nDescr],
+ pSource + pMemberOffsets[nDescr],
+ ppTypeRefs[nDescr], acquire );
+ }
+ }
+ }
+
+ TYPELIB_DANGER_RELEASE( pElementTypeDescr );
+ break;
+ }
+ case typelib_TypeClass_SEQUENCE: // sequence of sequence
+ {
+ // coverity[suspicious_sizeof : FALSE] - sizeof(uno_Sequence*) is correct here
+ pSeq = reallocSeq(pSeq, sizeof(uno_Sequence*), nAlloc);
+ if (pSeq != nullptr)
+ {
+ typelib_TypeDescription * pElementTypeDescr = nullptr;
+ TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
+ typelib_TypeDescriptionReference * pSeqElementType =
+ reinterpret_cast<typelib_IndirectTypeDescription *>(pElementTypeDescr)->pType;
+ uno_Sequence ** pDestElements = reinterpret_cast<uno_Sequence **>(pSeq->elements);
+ for ( sal_Int32 nPos = 0; nPos < nStopIndex; ++nPos )
+ {
+ uno_Sequence * pNew = icopyConstructSequence(
+ static_cast<uno_Sequence **>(pSourceElements)[nPos],
+ pSeqElementType, acquire, nullptr );
+ OSL_ASSERT( pNew != nullptr );
+ // ought never be a memory allocation problem,
+ // because of reference counted sequence handles
+ pDestElements[ nPos ] = pNew;
+ }
+ TYPELIB_DANGER_RELEASE( pElementTypeDescr );
+ }
+ break;
+ }
+ case typelib_TypeClass_INTERFACE:
+ {
+ pSeq = reallocSeq( pSeq, sizeof(void *), nAlloc );
+ if (pSeq != nullptr)
+ {
+ void ** pDestElements = reinterpret_cast<void **>(pSeq->elements);
+ for ( sal_Int32 nPos = 0; nPos < nStopIndex; ++nPos )
+ {
+ pDestElements[nPos] = static_cast<void **>(pSourceElements)[nPos];
+ _acquire( pDestElements[nPos], acquire );
+ }
+ }
+ break;
+ }
+ default:
+ OSL_FAIL( "### unexpected element type!" );
+ pSeq = nullptr;
+ break;
+ }
+
+ if (pSeq == nullptr)
+ {
+ return false; // allocation failure
+ }
+ *ppSeq = pSeq;
+ return true;
+}
+
+
+static bool ireallocSequence(
+ uno_Sequence ** ppSequence,
+ typelib_TypeDescriptionReference * pElementType,
+ sal_Int32 nSize,
+ uno_AcquireFunc acquire, uno_ReleaseFunc release )
+{
+ bool ret = true;
+ uno_Sequence * pSeq = *ppSequence;
+ sal_Int32 nElements = pSeq->nElements;
+
+ if (pSeq->nRefCount > 1 ||
+ // not mem-copyable elements?
+ typelib_TypeClass_ANY == pElementType->eTypeClass ||
+ typelib_TypeClass_STRUCT == pElementType->eTypeClass ||
+ typelib_TypeClass_EXCEPTION == pElementType->eTypeClass)
+ {
+ // split sequence and construct new one from scratch
+ uno_Sequence * pNew = nullptr;
+
+ sal_Int32 nRest = nSize - nElements;
+ sal_Int32 nCopy = (nRest > 0 ? nElements : nSize);
+
+ if (nCopy >= 0)
+ {
+ ret = icopyConstructFromElements(
+ &pNew, pSeq->elements, pElementType,
+ nCopy, acquire,
+ nSize ); // alloc to nSize
+ }
+ if (ret && nRest > 0)
+ {
+ ret = idefaultConstructElements(
+ &pNew, pElementType,
+ nCopy, nSize,
+ nCopy >= 0 ? -1 /* no mem allocation */ : nSize );
+ }
+
+ if (ret)
+ {
+ // destruct sequence
+ if (osl_atomic_decrement( &pSeq->nRefCount ) == 0)
+ {
+ if (nElements > 0)
+ {
+ idestructElements(
+ pSeq->elements, pElementType,
+ 0, nElements, release );
+ }
+ std::free( pSeq );
+ }
+ *ppSequence = pNew;
+ }
+ }
+ else
+ {
+ OSL_ASSERT( pSeq->nRefCount == 1 );
+ if (nSize > nElements) // default construct the rest
+ {
+ ret = idefaultConstructElements(
+ ppSequence, pElementType,
+ nElements, nSize,
+ nSize ); // realloc to nSize
+ }
+ else // or destruct the rest and realloc mem
+ {
+ sal_Int32 nElementSize = idestructElements(
+ pSeq->elements, pElementType,
+ nSize, nElements, release );
+ // warning: it is assumed that the following will never fail,
+ // else this leads to a sequence null handle
+ *ppSequence = reallocSeq( pSeq, nElementSize, nSize );
+ OSL_ASSERT( *ppSequence != nullptr );
+ ret = (*ppSequence != nullptr);
+ }
+ }
+
+ return ret;
+}
+
+}
+
+extern "C"
+{
+
+sal_Bool SAL_CALL uno_type_sequence_construct(
+ uno_Sequence ** ppSequence, typelib_TypeDescriptionReference * pType,
+ void * pElements, sal_Int32 len,
+ uno_AcquireFunc acquire )
+ SAL_THROW_EXTERN_C()
+{
+ assert( len >= 0 );
+ bool ret;
+ if (len)
+ {
+ typelib_TypeDescription * pTypeDescr = nullptr;
+ TYPELIB_DANGER_GET( &pTypeDescr, pType );
+
+ typelib_TypeDescriptionReference * pElementType =
+ reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType;
+
+ *ppSequence = nullptr;
+ if (pElements == nullptr)
+ {
+ ret = idefaultConstructElements(
+ ppSequence, pElementType,
+ 0, len,
+ len ); // alloc to len
+ }
+ else
+ {
+ ret = icopyConstructFromElements(
+ ppSequence, pElements, pElementType,
+ len, acquire,
+ len ); // alloc to len
+ }
+
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ }
+ else
+ {
+ *ppSequence = createEmptySequence();
+ ret = true;
+ }
+
+ OSL_ASSERT( (*ppSequence != nullptr) == ret );
+ return ret;
+}
+
+
+sal_Bool SAL_CALL uno_sequence_construct(
+ uno_Sequence ** ppSequence, typelib_TypeDescription * pTypeDescr,
+ void * pElements, sal_Int32 len,
+ uno_AcquireFunc acquire )
+ SAL_THROW_EXTERN_C()
+{
+ bool ret;
+ if (len > 0)
+ {
+ typelib_TypeDescriptionReference * pElementType =
+ reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType;
+
+ *ppSequence = nullptr;
+ if (pElements == nullptr)
+ {
+ ret = idefaultConstructElements(
+ ppSequence, pElementType,
+ 0, len,
+ len ); // alloc to len
+ }
+ else
+ {
+ ret = icopyConstructFromElements(
+ ppSequence, pElements, pElementType,
+ len, acquire,
+ len ); // alloc to len
+ }
+ }
+ else
+ {
+ *ppSequence = createEmptySequence();
+ ret = true;
+ }
+
+ OSL_ASSERT( (*ppSequence != nullptr) == ret );
+ return ret;
+}
+
+
+sal_Bool SAL_CALL uno_type_sequence_realloc(
+ uno_Sequence ** ppSequence, typelib_TypeDescriptionReference * pType,
+ sal_Int32 nSize, uno_AcquireFunc acquire, uno_ReleaseFunc release )
+ SAL_THROW_EXTERN_C()
+{
+ assert(ppSequence && "### null ptr!");
+ assert(nSize >= 0 && "### new size must be at least 0!");
+
+ bool ret = true;
+ if (nSize != (*ppSequence)->nElements)
+ {
+ typelib_TypeDescription * pTypeDescr = nullptr;
+ TYPELIB_DANGER_GET( &pTypeDescr, pType );
+ ret = ireallocSequence(
+ ppSequence, reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType,
+ nSize, acquire, release );
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ }
+ return ret;
+}
+
+
+sal_Bool SAL_CALL uno_sequence_realloc(
+ uno_Sequence ** ppSequence, typelib_TypeDescription * pTypeDescr,
+ sal_Int32 nSize, uno_AcquireFunc acquire, uno_ReleaseFunc release )
+ SAL_THROW_EXTERN_C()
+{
+ OSL_ENSURE( ppSequence, "### null ptr!" );
+ OSL_ENSURE( nSize >= 0, "### new size must be at least 0!" );
+
+ bool ret = true;
+ if (nSize != (*ppSequence)->nElements)
+ {
+ ret = ireallocSequence(
+ ppSequence, reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType,
+ nSize, acquire, release );
+ }
+ return ret;
+}
+
+
+sal_Bool SAL_CALL uno_type_sequence_reference2One(
+ uno_Sequence ** ppSequence,
+ typelib_TypeDescriptionReference * pType,
+ uno_AcquireFunc acquire, uno_ReleaseFunc release )
+ SAL_THROW_EXTERN_C()
+{
+ OSL_ENSURE( ppSequence, "### null ptr!" );
+ bool ret = true;
+ uno_Sequence * pSequence = *ppSequence;
+ if (pSequence->nRefCount > 1)
+ {
+ uno_Sequence * pNew = nullptr;
+ if (pSequence->nElements > 0)
+ {
+ typelib_TypeDescription * pTypeDescr = nullptr;
+ TYPELIB_DANGER_GET( &pTypeDescr, pType );
+
+ ret = icopyConstructFromElements(
+ &pNew, pSequence->elements,
+ reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType,
+ pSequence->nElements, acquire,
+ pSequence->nElements ); // alloc nElements
+ if (ret)
+ {
+ idestructSequence( *ppSequence, pType, pTypeDescr, release );
+ *ppSequence = pNew;
+ }
+
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ }
+ else
+ {
+ pNew = allocSeq( 0, 0 );
+ ret = (pNew != nullptr);
+ if (ret)
+ {
+ // easy destruction of empty sequence:
+ if (osl_atomic_decrement( &pSequence->nRefCount ) == 0)
+ std::free( pSequence );
+ *ppSequence = pNew;
+ }
+ }
+ }
+ return ret;
+}
+
+
+sal_Bool SAL_CALL uno_sequence_reference2One(
+ uno_Sequence ** ppSequence,
+ typelib_TypeDescription * pTypeDescr,
+ uno_AcquireFunc acquire, uno_ReleaseFunc release )
+ SAL_THROW_EXTERN_C()
+{
+ OSL_ENSURE( ppSequence, "### null ptr!" );
+ bool ret = true;
+ uno_Sequence * pSequence = *ppSequence;
+ if (pSequence->nRefCount > 1)
+ {
+ uno_Sequence * pNew = nullptr;
+ if (pSequence->nElements > 0)
+ {
+ ret = icopyConstructFromElements(
+ &pNew, pSequence->elements,
+ reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType,
+ pSequence->nElements, acquire,
+ pSequence->nElements ); // alloc nElements
+ if (ret)
+ {
+ idestructSequence(
+ pSequence, pTypeDescr->pWeakRef, pTypeDescr, release );
+ *ppSequence = pNew;
+ }
+ }
+ else
+ {
+ pNew = allocSeq( 0, 0 );
+ ret = (pNew != nullptr);
+ if (ret)
+ {
+ // easy destruction of empty sequence:
+ if (osl_atomic_decrement( &pSequence->nRefCount ) == 0)
+ std::free( pSequence );
+ *ppSequence = pNew;
+ }
+ }
+
+ }
+ return ret;
+}
+
+
+void SAL_CALL uno_sequence_assign(
+ uno_Sequence ** ppDest,
+ uno_Sequence * pSource,
+ typelib_TypeDescription * pTypeDescr,
+ uno_ReleaseFunc release )
+ SAL_THROW_EXTERN_C()
+{
+ if (*ppDest != pSource)
+ {
+ osl_atomic_increment( &pSource->nRefCount );
+ idestructSequence( *ppDest, pTypeDescr->pWeakRef, pTypeDescr, release );
+ *ppDest = pSource;
+ }
+}
+
+
+void SAL_CALL uno_type_sequence_assign(
+ uno_Sequence ** ppDest,
+ uno_Sequence * pSource,
+ typelib_TypeDescriptionReference * pType,
+ uno_ReleaseFunc release )
+ SAL_THROW_EXTERN_C()
+{
+ if (*ppDest != pSource)
+ {
+ osl_atomic_increment( &pSource->nRefCount );
+ idestructSequence( *ppDest, pType, nullptr, release );
+ *ppDest = pSource;
+ }
+}
+
+void uno_type_sequence_destroy(
+ uno_Sequence * sequence, typelib_TypeDescriptionReference * type,
+ uno_ReleaseFunc release)
+ SAL_THROW_EXTERN_C()
+{
+ idestroySequence(sequence, type, nullptr, release);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppu/util/cppu.map b/cppu/util/cppu.map
new file mode 100644
index 000000000..df724a5c9
--- /dev/null
+++ b/cppu/util/cppu.map
@@ -0,0 +1,158 @@
+#
+# 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 .
+#
+UDK_3_0_0 {
+ global:
+ _ZTI*; _ZTS*; # weak RTTI symbols for C++ exceptions
+
+ typelib_typedescription_new;
+ typelib_typedescription_newInterface;
+ typelib_typedescription_newInterfaceMethod;
+ typelib_typedescription_newInterfaceAttribute;
+ typelib_typedescription_newEnum;
+ typelib_typedescription_newUnion;
+ typelib_typedescription_newArray;
+ typelib_typedescription_acquire;
+ typelib_typedescription_release;
+ typelib_typedescription_register;
+ typelib_typedescription_equals;
+ typelib_typedescription_isAssignableFrom;
+ typelib_typedescription_getByName;
+ typelib_typedescription_registerCallback;
+ typelib_typedescription_revokeCallback;
+ typelib_typedescriptionreference_new;
+ typelib_typedescriptionreference_acquire;
+ typelib_typedescriptionreference_release;
+ typelib_typedescriptionreference_getDescription;
+ typelib_typedescriptionreference_equals;
+ typelib_typedescriptionreference_assign;
+ typelib_typedescriptionreference_isAssignableFrom;
+
+ typelib_setCacheSize;
+
+ typelib_typedescriptionreference_newByAsciiName;
+ typelib_static_type_getByTypeClass;
+ typelib_static_type_init;
+ typelib_static_sequence_type_init;
+ typelib_static_compound_type_init;
+ typelib_static_interface_type_init;
+ typelib_static_enum_type_init;
+ typelib_static_array_type_init;
+ typelib_typedescription_complete;
+
+ uno_equalData;
+ uno_type_equalData;
+ uno_constructData;
+ uno_type_constructData;
+ uno_destructData;
+ uno_type_destructData;
+ uno_copyData;
+ uno_type_copyData;
+ uno_copyAndConvertData;
+ uno_type_copyAndConvertData;
+ uno_assignData;
+ uno_type_assignData;
+ uno_type_isAssignableFromData;
+
+ uno_any_assign;
+ uno_type_any_assign;
+ uno_any_construct;
+ uno_type_any_construct;
+ uno_any_constructAndConvert;
+ uno_type_any_constructAndConvert;
+ uno_any_destruct;
+ uno_any_clear;
+
+ uno_sequence_assign;
+ uno_type_sequence_assign;
+ uno_sequence_construct;
+ uno_type_sequence_construct;
+ uno_sequence_reference2One;
+ uno_type_sequence_reference2One;
+ uno_sequence_realloc;
+ uno_type_sequence_realloc;
+
+ uno_createEnvironment;
+ uno_getEnvironment;
+ uno_getRegisteredEnvironments;
+ uno_dumpEnvironment;
+ uno_dumpEnvironmentByName;
+ uno_getMapping;
+ uno_getMappingByName;
+ uno_registerMapping;
+ uno_revokeMapping;
+ uno_registerMappingCallback;
+ uno_revokeMappingCallback;
+
+ uno_getCurrentContext;
+ uno_setCurrentContext;
+
+ uno_bindIdToCurrentThread;
+ uno_getIdOfCurrentThread;
+ uno_releaseIdFromCurrentThread;
+ uno_threadpool_enter;
+ uno_threadpool_create;
+ uno_threadpool_destroy;
+ uno_threadpool_putJob;
+ uno_threadpool_dispose;
+ uno_threadpool_attach;
+ uno_threadpool_detach;
+
+ cppu_unsatisfied_iquery_msg;
+ local:
+ *;
+};
+
+UDK_3.1 {
+ global:
+ typelib_static_mi_interface_type_init;
+ typelib_static_struct_type_init;
+ typelib_typedescription_newExtendedInterfaceAttribute;
+ typelib_typedescription_newMIInterface;
+ typelib_typedescription_newStruct;
+ cppu_Any_extraction_failure_msg;
+} UDK_3_0_0;
+
+UDK_3.2 {
+ global:
+ uno_EnvDcp_getTypeName;
+ uno_EnvDcp_getPurpose;
+
+ uno_getCurrentEnvironment;
+ uno_Environment_invoke_v;
+ uno_Environment_invoke;
+ uno_Environment_enter;
+
+ uno_Environment_isValid;
+} UDK_3.1;
+
+UDK_3.3 { # OOo 2.4
+ global:
+ cppu_unsatisfied_iset_msg;
+} UDK_3.2;
+
+LIBO_UDK_4.4 { # symbols available in >= LibO 4.4
+ global:
+ uno_type_sequence_destroy;
+} UDK_3.3;
+
+# Unique libstdc++ symbols:
+GLIBCXX_3.4 {
+ global:
+ _ZGVNSt7num_put*; _ZNSt7num_put*;
+ _ZNSs4_Rep20_S_empty_rep_storageE;
+};
diff --git a/cppu/util/uno_purpenvhelpergcc3.map b/cppu/util/uno_purpenvhelpergcc3.map
new file mode 100644
index 000000000..7aec7b55f
--- /dev/null
+++ b/cppu/util/uno_purpenvhelpergcc3.map
@@ -0,0 +1,34 @@
+#
+# 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 .
+#
+UDK_3_0_0 {
+ global:
+ _ZTI*; _ZTS*; # weak RTTI symbols for C++ exceptions
+
+ _ZN4cppu6helper7purpenv13createMappingEPP12_uno_MappingP16_uno_EnvironmentS6_PFvbPvS7_P33_typelib_TypeDescriptionReferenceP24_typelib_MethodParameter?PK24_typelib_TypeDescriptionS7_PS7_PP8_uno_AnyES7_;
+ _ZN4cppu6helper7purpenv29Environment_initWithEnterableEP16_uno_EnvironmentPNS_9EnterableE;
+
+ local:
+ *;
+};
+
+# Unique libstdc++ symbols:
+GLIBCXX_3.4 {
+ global:
+ _ZGVNSt7num_put*; _ZNSt7num_put*;
+ _ZNSs4_Rep20_S_empty_rep_storageE;
+};
diff --git a/cppuhelper/CppunitTest_cppuhelper_cppu_ifcontainer.mk b/cppuhelper/CppunitTest_cppuhelper_cppu_ifcontainer.mk
new file mode 100644
index 000000000..1d745b641
--- /dev/null
+++ b/cppuhelper/CppunitTest_cppuhelper_cppu_ifcontainer.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,cppuhelper_cppu_ifcontainer))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,cppuhelper_cppu_ifcontainer,\
+ cppuhelper/qa/ifcontainer/cppu_ifcontainer \
+))
+
+$(eval $(call gb_CppunitTest_use_api,cppuhelper_cppu_ifcontainer,\
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,cppuhelper_cppu_ifcontainer,\
+ cppu \
+ cppuhelper \
+ sal \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppuhelper/CppunitTest_cppuhelper_cppu_unourl.mk b/cppuhelper/CppunitTest_cppuhelper_cppu_unourl.mk
new file mode 100644
index 000000000..d973e748d
--- /dev/null
+++ b/cppuhelper/CppunitTest_cppuhelper_cppu_unourl.mk
@@ -0,0 +1,23 @@
+# -*- 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,cppuhelper_cppu_unourl))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,cppuhelper_cppu_unourl,\
+ cppuhelper/qa/unourl/cppu_unourl \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,cppuhelper_cppu_unourl,\
+ cppu \
+ cppuhelper \
+ sal \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppuhelper/CppunitTest_cppuhelper_qa_misc.mk b/cppuhelper/CppunitTest_cppuhelper_qa_misc.mk
new file mode 100644
index 000000000..c83ebee59
--- /dev/null
+++ b/cppuhelper/CppunitTest_cppuhelper_qa_misc.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,cppuhelper_qa_misc))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,cppuhelper_qa_misc,\
+ cppuhelper/qa/misc/test_misc \
+))
+
+$(eval $(call gb_CppunitTest_use_api,cppuhelper_qa_misc,\
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,cppuhelper_qa_misc,\
+ cppu \
+ cppuhelper \
+ sal \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppuhelper/CppunitTest_cppuhelper_qa_weak.mk b/cppuhelper/CppunitTest_cppuhelper_qa_weak.mk
new file mode 100644
index 000000000..9a6322caf
--- /dev/null
+++ b/cppuhelper/CppunitTest_cppuhelper_qa_weak.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,cppuhelper_qa_weak))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,cppuhelper_qa_weak,\
+ cppuhelper/qa/weak/test_weak \
+))
+
+$(eval $(call gb_CppunitTest_use_api,cppuhelper_qa_weak,\
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,cppuhelper_qa_weak,\
+ cppu \
+ cppuhelper \
+ sal \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppuhelper/InternalUnoApi_cppuhelper.mk b/cppuhelper/InternalUnoApi_cppuhelper.mk
new file mode 100644
index 000000000..d2849b0a3
--- /dev/null
+++ b/cppuhelper/InternalUnoApi_cppuhelper.mk
@@ -0,0 +1,20 @@
+# -*- 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_InternalUnoApi_InternalUnoApi,cppuhelper,cppuhelper/unotypes))
+
+$(eval $(call gb_InternalUnoApi_use_api,cppuhelper,\
+ udkapi \
+))
+
+$(eval $(call gb_InternalUnoApi_add_idlfiles,cppuhelper,cppuhelper/detail,\
+ XExceptionThrower \
+))
+
+# vim:set noet sw=4 ts=4:
diff --git a/cppuhelper/IwyuFilter_cppuhelper.yaml b/cppuhelper/IwyuFilter_cppuhelper.yaml
new file mode 100644
index 000000000..cbae100fb
--- /dev/null
+++ b/cppuhelper/IwyuFilter_cppuhelper.yaml
@@ -0,0 +1,59 @@
+---
+assumeFilename: cppuhelper/source/implbase.cxx
+excludelist:
+ cppuhelper/source/typemanager.hxx:
+ # base class needs full type
+ - com/sun/star/container/XHierarchicalNameAccess.hpp
+ - com/sun/star/container/XSet.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp
+ - cppuhelper/compbase.hxx
+ cppuhelper/source/access_control.cxx:
+ # Needed for UnoType
+ - com/sun/star/security/RuntimePermission.hpp
+ - com/sun/star/io/FilePermission.hpp
+ - com/sun/star/connection/SocketPermission.hpp
+ cppuhelper/source/bootstrap.cxx:
+ # Needed on win32
+ - o3tl/char16_t2wchar_t.hxx
+ cppuhelper/source/defaultbootstrap.cxx:
+ # Needed for template specialization
+ - com/sun/star/lang/XSingleComponentFactory.hpp
+ cppuhelper/source/exc_thrower.cxx:
+ # No hpp -> hdl switch
+ - cppuhelper/detail/XExceptionThrower.hpp
+ # Needed for mobile versions
+ - sal/log.hxx
+ - com/sun/star/ucb/InteractiveAugmentedIOException.hpp
+ - com/sun/star/ucb/NameClashException.hpp
+ # Needed for cppu::throwException
+ - cppuhelper/exc_hlp.hxx
+ cppuhelper/source/findsofficepath.c:
+ # Needed for cppuhelper_detail_findSofficePath
+ - cppuhelper/findsofficepath.h
+ cppuhelper/source/macro_expander.cxx:
+ # Needed for template specialization
+ - com/sun/star/lang/XSingleComponentFactory.hpp
+ cppuhelper/source/paths.cxx:
+ # Needed on mac OS for LIBO_LIB_FOLDER + LIBO_URE_ETC_FOLDER
+ - config_folders.h
+ cppuhelper/source/shlib.cxx:
+ # Needed for UnoType
+ - com/sun/star/registry/XRegistryKey.hpp
+ # Needed for loadSharedLibComponentFactory & writeSharedLibComponentInfo
+ - cppuhelper/shlib.hxx
+ # Needed for cppuhelper::detail::getEnvironment
+ - loadsharedlibcomponentfactory.hxx
+ cppuhelper/source/supportsservice.cxx:
+ # Needed for supportsService
+ - cppuhelper/supportsservice.hxx
+ cppuhelper/source/tdmgr.cxx:
+ # Needed to inherit linker visibility from function declaration
+ - cppuhelper/bootstrap.hxx
+ cppuhelper/source/typemanager.cxx:
+ # Actually used
+ - com/sun/star/reflection/TypeDescriptionSearchDepth.hpp
+ - com/sun/star/uno/TypeClass.hpp
+ cppuhelper/source/servicemanager.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
diff --git a/cppuhelper/Library_cppuhelper.mk b/cppuhelper/Library_cppuhelper.mk
new file mode 100644
index 000000000..dbbfa55d5
--- /dev/null
+++ b/cppuhelper/Library_cppuhelper.mk
@@ -0,0 +1,75 @@
+# -*- 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_Library_Library,cppuhelper))
+
+$(eval $(call gb_Library_set_soversion_script,cppuhelper,$(SRCDIR)/cppuhelper/source/gcc3.map))
+
+$(eval $(call gb_Library_set_precompiled_header,cppuhelper,cppuhelper/inc/pch/precompiled_cppuhelper))
+
+$(eval $(call gb_Library_use_internal_comprehensive_api,cppuhelper,\
+ cppuhelper \
+ udkapi \
+ offapi \
+))
+
+$(eval $(call gb_Library_set_is_ure_library_or_dependency,cppuhelper))
+
+$(eval $(call gb_Library_add_defs,cppuhelper,\
+ -DCPPUHELPER_DLLIMPLEMENTATION \
+))
+
+$(eval $(call gb_Library_use_libraries,cppuhelper,\
+ cppu \
+ reg \
+ sal \
+ salhelper \
+ unoidl \
+ xmlreader \
+))
+
+$(eval $(call gb_Library_use_static_libraries,cppuhelper,\
+ findsofficepath \
+))
+
+ifeq ($(OS),iOS)
+$(eval $(call gb_Library_add_cxxflags,cppuhelper,\
+ $(gb_OBJCXXFLAGS) \
+))
+endif
+
+$(eval $(call gb_Library_add_exception_objects,cppuhelper,\
+ cppuhelper/source/access_control \
+ cppuhelper/source/bootstrap \
+ cppuhelper/source/compat \
+ cppuhelper/source/component_context \
+ cppuhelper/source/component \
+ cppuhelper/source/defaultbootstrap \
+ cppuhelper/source/exc_thrower \
+ cppuhelper/source/factory \
+ cppuhelper/source/implbase \
+ cppuhelper/source/implbase_ex \
+ cppuhelper/source/implementationentry \
+ cppuhelper/source/interfacecontainer \
+ cppuhelper/source/macro_expander \
+ cppuhelper/source/paths \
+ cppuhelper/source/propertysetmixin \
+ cppuhelper/source/propshlp \
+ cppuhelper/source/servicemanager \
+ cppuhelper/source/shlib \
+ cppuhelper/source/supportsservice \
+ cppuhelper/source/tdmgr \
+ cppuhelper/source/typemanager \
+ cppuhelper/source/typeprovider \
+ cppuhelper/source/unourl \
+ cppuhelper/source/weak \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppuhelper/Makefile b/cppuhelper/Makefile
new file mode 100644
index 000000000..0997e6284
--- /dev/null
+++ b/cppuhelper/Makefile
@@ -0,0 +1,14 @@
+# -*- 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/.
+#
+
+module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
+
+include $(module_directory)/../solenv/gbuild/partial_build.mk
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppuhelper/Module_cppuhelper.mk b/cppuhelper/Module_cppuhelper.mk
new file mode 100644
index 000000000..35b95e5ab
--- /dev/null
+++ b/cppuhelper/Module_cppuhelper.mk
@@ -0,0 +1,26 @@
+# -*- 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_Module_Module,cppuhelper))
+
+$(eval $(call gb_Module_add_targets,cppuhelper,\
+ InternalUnoApi_cppuhelper \
+ Library_cppuhelper \
+ StaticLibrary_findsofficepath \
+))
+
+$(eval $(call gb_Module_add_check_targets,cppuhelper,\
+ CppunitTest_cppuhelper_cppu_ifcontainer \
+ CppunitTest_cppuhelper_cppu_unourl \
+ CppunitTest_cppuhelper_qa_misc \
+ CppunitTest_cppuhelper_qa_weak \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppuhelper/README.md b/cppuhelper/README.md
new file mode 100644
index 000000000..1da7282a9
--- /dev/null
+++ b/cppuhelper/README.md
@@ -0,0 +1,8 @@
+# C++ cppu Helpers
+
+Helpers for using `cppu` in C++, e.g. templates for implementing UNO components, bootstrapping
+stuff. Get UNO up and running.
+
+## See Also
+
+<http://wiki.openoffice.org/wiki/Uno/Cpp/Modules/CPPUhelper>
diff --git a/cppuhelper/StaticLibrary_findsofficepath.mk b/cppuhelper/StaticLibrary_findsofficepath.mk
new file mode 100644
index 000000000..080f20b54
--- /dev/null
+++ b/cppuhelper/StaticLibrary_findsofficepath.mk
@@ -0,0 +1,16 @@
+# -*- 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_StaticLibrary_StaticLibrary,findsofficepath))
+
+$(eval $(call gb_StaticLibrary_add_cobjects,findsofficepath,\
+ cppuhelper/source/findsofficepath \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/cppuhelper/inc/pch/precompiled_cppuhelper.cxx b/cppuhelper/inc/pch/precompiled_cppuhelper.cxx
new file mode 100644
index 000000000..1c3b45036
--- /dev/null
+++ b/cppuhelper/inc/pch/precompiled_cppuhelper.cxx
@@ -0,0 +1,12 @@
+/* -*- 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 "precompiled_cppuhelper.hxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/inc/pch/precompiled_cppuhelper.hxx b/cppuhelper/inc/pch/precompiled_cppuhelper.hxx
new file mode 100644
index 000000000..81d17c22d
--- /dev/null
+++ b/cppuhelper/inc/pch/precompiled_cppuhelper.hxx
@@ -0,0 +1,111 @@
+/* -*- 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 has been autogenerated by update_pch.sh. It is possible to edit it
+ manually (such as when an include file has been moved/renamed/removed). All such
+ manual changes will be rewritten by the next run of update_pch.sh (which presumably
+ also fixes all possible problems, so it's usually better to use it).
+
+ Generated on 2021-04-08 13:50:34 using:
+ ./bin/update_pch cppuhelper cppuhelper --cutoff=3 --exclude:system --exclude:module --exclude:local
+
+ If after updating build fails, use the following command to locate conflicting headers:
+ ./bin/update_pch_bisect ./cppuhelper/inc/pch/precompiled_cppuhelper.hxx "make cppuhelper.build" --find-conflicts
+*/
+
+#include <sal/config.h>
+#if PCH_LEVEL >= 1
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdlib>
+#include <memory>
+#include <new>
+#include <type_traits>
+#include <vector>
+#endif // PCH_LEVEL >= 1
+#if PCH_LEVEL >= 2
+#include <osl/diagnose.h>
+#include <osl/file.hxx>
+#include <osl/interlck.h>
+#include <osl/module.h>
+#include <osl/module.hxx>
+#include <osl/mutex.hxx>
+#include <osl/process.h>
+#include <osl/security.hxx>
+#include <osl/thread.hxx>
+#include <osl/time.h>
+#include <rtl/alloc.h>
+#include <rtl/bootstrap.hxx>
+#include <rtl/character.hxx>
+#include <rtl/malformeduriexception.hxx>
+#include <rtl/random.h>
+#include <rtl/ref.hxx>
+#include <rtl/unload.h>
+#include <rtl/uri.h>
+#include <rtl/uri.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.h>
+#include <rtl/ustring.hxx>
+#include <rtl/uuid.h>
+#include <sal/log.hxx>
+#include <sal/macros.h>
+#include <sal/saldllapi.h>
+#include <sal/types.h>
+#endif // PCH_LEVEL >= 2
+#if PCH_LEVEL >= 3
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XSingleComponentFactory.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/reflection/XIndirectTypeDescription.hpp>
+#include <com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp>
+#include <com/sun/star/reflection/XInterfaceTypeDescription2.hpp>
+#include <com/sun/star/reflection/XStructTypeDescription.hpp>
+#include <com/sun/star/reflection/XTypeDescription.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/DeploymentException.hpp>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Type.h>
+#include <com/sun/star/uno/XAggregation.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/sequence.hxx>
+#include <cppu/cppudllapi.h>
+#include <salhelper/simplereferenceobject.hxx>
+#include <typelib/typeclass.h>
+#include <typelib/typedescription.h>
+#include <typelib/uik.h>
+#include <uno/lbnames.h>
+#include <uno/mapping.hxx>
+#endif // PCH_LEVEL >= 3
+#if PCH_LEVEL >= 4
+#include <cppuhelper/bootstrap.hxx>
+#include <cppuhelper/component_context.hxx>
+#include <cppuhelper/cppuhelperdllapi.h>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/interfacecontainer.h>
+#include <cppuhelper/propshlp.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/weak.hxx>
+#include <cppuhelper/weakagg.hxx>
+#include <cppuhelper/weakref.hxx>
+#endif // PCH_LEVEL >= 4
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/qa/ifcontainer/cppu_ifcontainer.cxx b/cppuhelper/qa/ifcontainer/cppu_ifcontainer.cxx
new file mode 100644
index 000000000..0dcebbbac
--- /dev/null
+++ b/cppuhelper/qa/ifcontainer/cppu_ifcontainer.cxx
@@ -0,0 +1,263 @@
+/* -*- 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/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <com/sun/star/lang/XEventListener.hpp>
+#include <cppuhelper/interfacecontainer.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/propshlp.hxx>
+
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+
+namespace {
+
+struct ContainerStats {
+ int m_nAlive;
+ int m_nDisposed;
+ ContainerStats() : m_nAlive(0), m_nDisposed(0) {}
+};
+
+class ContainerListener : public ::cppu::WeakImplHelper< XEventListener >
+{
+ ContainerStats *m_pStats;
+public:
+ explicit ContainerListener(ContainerStats *pStats)
+ : m_pStats(pStats) { m_pStats->m_nAlive++; }
+ virtual ~ContainerListener() override { m_pStats->m_nAlive--; }
+ virtual void SAL_CALL disposing( const EventObject& ) override
+ {
+ m_pStats->m_nDisposed++;
+ }
+};
+
+}
+
+namespace cppu_ifcontainer
+{
+ class IfTest : public CppUnit::TestFixture
+ {
+ osl::Mutex m_aGuard;
+ static const int nTests = 10;
+ public:
+ void testCreateDispose()
+ {
+ ContainerStats aStats;
+ cppu::OInterfaceContainerHelper *pContainer;
+
+ pContainer = new cppu::OInterfaceContainerHelper(m_aGuard);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Empty container not empty",
+ static_cast<sal_Int32>(0), pContainer->getLength());
+
+ int i;
+ for (i = 0; i < nTests; i++)
+ {
+ Reference<XEventListener> xRef = new ContainerListener(&aStats);
+ int nNewLen = pContainer->addInterface(xRef);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("addition length mismatch",
+ i + 1, nNewLen);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("addition length mismatch",
+ static_cast<sal_Int32>(i + 1), pContainer->getLength());
+ }
+ CPPUNIT_ASSERT_MESSAGE("alive count mismatch",
+ bool(aStats.m_nAlive == nTests));
+
+ EventObject aObj;
+ pContainer->disposeAndClear(aObj);
+
+ CPPUNIT_ASSERT_MESSAGE("dispose count mismatch",
+ bool(aStats.m_nDisposed == nTests));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("leaked container left alive",
+ 0, aStats.m_nAlive);
+
+ delete pContainer;
+ }
+
+ void testEnumerate()
+ {
+ int i;
+ ContainerStats aStats;
+ cppu::OInterfaceContainerHelper *pContainer;
+ pContainer = new cppu::OInterfaceContainerHelper(m_aGuard);
+
+ std::vector< Reference< XEventListener > > aListeners;
+ for (i = 0; i < nTests; i++)
+ {
+ Reference<XEventListener> xRef = new ContainerListener(&aStats);
+ pContainer->addInterface(xRef);
+ aListeners.push_back(xRef);
+ }
+ Sequence< Reference< XInterface > > aElements = pContainer->getElements();
+
+ CPPUNIT_ASSERT_MESSAGE("query contents",
+ bool(static_cast<int>(aElements.getLength()) == nTests));
+ if (static_cast<int>(aElements.getLength()) == nTests)
+ {
+ for (i = 0; i < nTests; i++)
+ {
+ CPPUNIT_ASSERT_MESSAGE("mismatching elements",
+ bool(aElements[i] == aListeners[i]));
+ }
+ }
+ pContainer->clear();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("non-empty container post clear",
+ static_cast<sal_Int32>(0), pContainer->getLength());
+ delete pContainer;
+ }
+
+ template < typename ContainerType, typename ContainedType >
+ void doContainerTest(const ContainedType *pTypes)
+ {
+ ContainerStats aStats;
+ ContainerType *pContainer;
+ pContainer = new ContainerType(m_aGuard);
+
+ int i;
+ Reference<XEventListener> xRefs[nTests * 2];
+
+ // add these interfaces
+ for (i = 0; i < nTests * 2; i++)
+ {
+ xRefs[i] = new ContainerListener(&aStats);
+ pContainer->addInterface(pTypes[i / 2], xRefs[i]);
+ }
+
+ // check it is all there
+ for (i = 0; i < nTests; i++)
+ {
+ cppu::OInterfaceContainerHelper *pHelper;
+
+ pHelper = pContainer->getContainer(pTypes[i]);
+
+ CPPUNIT_ASSERT_MESSAGE("no helper", pHelper != nullptr);
+ Sequence<Reference< XInterface > > aSeq = pHelper->getElements();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong num elements", static_cast<sal_Int32>(2), aSeq.getLength());
+ CPPUNIT_ASSERT_MESSAGE("match", bool(aSeq[0] == xRefs[i*2]));
+ CPPUNIT_ASSERT_MESSAGE("match", bool(aSeq[1] == xRefs[i*2+1]));
+ }
+
+ // remove every other interface
+ for (i = 0; i < nTests; i++)
+ pContainer->removeInterface(pTypes[i], xRefs[i*2+1]);
+
+ // check it is half there
+ for (i = 0; i < nTests; i++)
+ {
+ cppu::OInterfaceContainerHelper *pHelper;
+
+ pHelper = pContainer->getContainer(pTypes[i]);
+
+ CPPUNIT_ASSERT_MESSAGE("no helper", pHelper != nullptr);
+ Sequence<Reference< XInterface > > aSeq = pHelper->getElements();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong num elements", static_cast<sal_Int32>(1), aSeq.getLength());
+ CPPUNIT_ASSERT_MESSAGE("match", bool(aSeq[0] == xRefs[i*2]));
+ }
+
+ // remove the 1st half of the rest
+ for (i = 0; i < nTests / 2; i++)
+ pContainer->removeInterface(pTypes[i], xRefs[i*2]);
+
+ // check it is half there
+ for (i = 0; i < nTests / 2; i++)
+ {
+ cppu::OInterfaceContainerHelper *pHelper;
+
+ pHelper = pContainer->getContainer(pTypes[i]);
+ CPPUNIT_ASSERT_MESSAGE("no helper", pHelper != nullptr);
+ Sequence<Reference< XInterface > > aSeq = pHelper->getElements();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong num elements", static_cast<sal_Int32>(0), aSeq.getLength());
+ }
+
+ delete pContainer;
+ }
+
+ void testOMultiTypeInterfaceContainerHelper()
+ {
+ uno::Type pTypes[nTests] =
+ {
+ ::cppu::UnoType< bool >::get(),
+ ::cppu::UnoType< float >::get(),
+ ::cppu::UnoType< double >::get(),
+ ::cppu::UnoType< ::sal_uInt64 >::get(),
+ ::cppu::UnoType< ::sal_Int64 >::get(),
+ ::cppu::UnoType< ::sal_uInt32 >::get(),
+ ::cppu::UnoType< ::sal_Int32 >::get(),
+ ::cppu::UnoType< ::sal_Int16 >::get(),
+ ::cppu::UnoType< OUString >::get(),
+ ::cppu::UnoType< ::sal_Int8 >::get()
+ };
+ doContainerTest< cppu::OMultiTypeInterfaceContainerHelper,
+ uno::Type> (pTypes);
+ }
+
+ void testOMultiTypeInterfaceContainerHelperInt32()
+ {
+ sal_Int32 const pTypes[nTests] =
+ {
+ 0,
+ -1,
+ 1,
+ 256,
+ 1024,
+ 3,
+ 7,
+ 8,
+ 9,
+ 10
+ };
+ doContainerTest< cppu::OMultiTypeInterfaceContainerHelperInt32, sal_Int32> (pTypes);
+ }
+
+ void testOMultiTypeInterfaceContainerHelperVar()
+ {
+ typedef cppu::OMultiTypeInterfaceContainerHelperVar<
+ char const *, void, rtl::CStringEqual> StrContainer;
+
+ const char * const pTypes[nTests] =
+ {
+ "this_is", "such", "fun", "writing", "unit", "tests", "when", "it", "works", "anyway"
+ };
+ doContainerTest< StrContainer, const char *> (pTypes);
+ }
+
+ // Automatic registration code
+ CPPUNIT_TEST_SUITE(IfTest);
+ CPPUNIT_TEST(testCreateDispose);
+ CPPUNIT_TEST(testEnumerate);
+ CPPUNIT_TEST(testOMultiTypeInterfaceContainerHelper);
+ CPPUNIT_TEST(testOMultiTypeInterfaceContainerHelperVar);
+ CPPUNIT_TEST(testOMultiTypeInterfaceContainerHelperInt32);
+ CPPUNIT_TEST_SUITE_END();
+ };
+} // namespace cppu_ifcontainer
+
+CPPUNIT_TEST_SUITE_REGISTRATION(cppu_ifcontainer::IfTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/qa/misc/test_misc.cxx b/cppuhelper/qa/misc/test_misc.cxx
new file mode 100644
index 000000000..0e4fdf9ef
--- /dev/null
+++ b/cppuhelper/qa/misc/test_misc.cxx
@@ -0,0 +1,91 @@
+/* -*- 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 <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <cppuhelper/exc_hlp.hxx>
+
+namespace
+{
+class Test : public ::CppUnit::TestFixture
+{
+public:
+ void testCatchThrow();
+ void testgetCaughtException();
+
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testCatchThrow);
+ CPPUNIT_TEST(testgetCaughtException);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void Test::testCatchThrow()
+{
+ css::uno::Any aSavedException;
+ try
+ {
+ throw css::uno::RuntimeException("RuntimeException");
+ }
+ catch (const css::uno::RuntimeException&)
+ {
+ aSavedException = cppu::getCaughtException();
+ }
+ CPPUNIT_ASSERT(aSavedException.hasValue());
+ try
+ {
+ cppu::throwException(aSavedException);
+ }
+ catch (const css::uno::RuntimeException&)
+ {
+ // the expected case
+ }
+ catch (...)
+ {
+ CPPUNIT_ASSERT(false);
+ }
+}
+
+void Test::testgetCaughtException()
+{
+ css::uno::Any aSavedExceptionAny;
+ std::exception_ptr
+ aSavedException; /// exception caught during unzipping is saved to be thrown during reading
+ try
+ {
+ throw css::uno::RuntimeException("RuntimeException");
+ }
+ catch (...)
+ {
+ aSavedException = std::current_exception();
+ }
+ CPPUNIT_ASSERT(bool(aSavedException));
+ try
+ {
+ std::rethrow_exception(aSavedException);
+ }
+ catch (const css::uno::RuntimeException&)
+ {
+ // the expected case
+ aSavedExceptionAny = cppu::getCaughtException();
+ }
+ catch (...)
+ {
+ CPPUNIT_ASSERT(false);
+ }
+ CPPUNIT_ASSERT(aSavedExceptionAny.hasValue());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/cppuhelper/qa/propertysetmixin/JavaSupplier.java b/cppuhelper/qa/propertysetmixin/JavaSupplier.java
new file mode 100644
index 000000000..a82e2bd7f
--- /dev/null
+++ b/cppuhelper/qa/propertysetmixin/JavaSupplier.java
@@ -0,0 +1,308 @@
+/*
+ * 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 test.cppuhelper.propertysetmixin.comp;
+
+import com.sun.star.beans.Ambiguous;
+import com.sun.star.beans.Defaulted;
+import com.sun.star.beans.Optional;
+import com.sun.star.beans.UnknownPropertyException;
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.beans.PropertyVetoException;
+import com.sun.star.beans.XFastPropertySet;
+import com.sun.star.beans.XPropertyAccess;
+import com.sun.star.beans.XPropertyChangeListener;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.beans.XPropertySetInfo;
+import com.sun.star.beans.XVetoableChangeListener;
+import com.sun.star.comp.loader.FactoryHelper;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.lang.XComponent;
+import com.sun.star.lang.XEventListener;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.lang.XSingleServiceFactory;
+import com.sun.star.lib.uno.helper.WeakBase;
+import com.sun.star.lib.uno.helper.PropertySetMixin;
+import com.sun.star.registry.XRegistryKey;
+import com.sun.star.uno.Any;
+import com.sun.star.uno.IQueryInterface;
+import com.sun.star.uno.Type;
+import com.sun.star.uno.XComponentContext;
+import test.cppuhelper.propertysetmixin.XSupplier;
+import test.cppuhelper.propertysetmixin.XTest3;
+
+public final class JavaSupplier extends WeakBase implements XSupplier {
+ public JavaSupplier(XComponentContext context) {
+ this.context = context;
+ }
+
+ public XComponent getEmpty1() { return new Empty1(); }
+
+ public XComponent getEmpty2() { return new Empty2(); }
+
+ public XTest3 getFull() { return new Full(); }
+
+ public static XSingleServiceFactory __getServiceFactory(
+ String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey)
+ {
+ return implName.equals(implementationName)
+ ? FactoryHelper.getServiceFactory(
+ JavaSupplier.class, serviceName, multiFactory, regKey)
+ : null;
+ }
+
+ private static final String implementationName
+ = JavaSupplier.class.getName();
+ private static final String serviceName
+ = "test.cppuhelper.propertysetmixin.JavaSupplier";
+
+ private final class Empty1 extends WeakBase implements XComponent {
+ public Empty1() {}
+
+ public void dispose() {
+ prop.dispose();
+ }
+
+ public void addEventListener(XEventListener listener) {}
+
+ public void removeEventListener(XEventListener listener) {}
+
+ private final PropertySetMixin prop = new PropertySetMixin(
+ context, this, new Type(XComponent.class), null);
+ }
+
+ private final class Empty2 extends WeakBase
+ implements XComponent, XPropertySet, XFastPropertySet, XPropertyAccess
+ {
+ public Empty2() {}
+
+ public void dispose() {
+ prop.dispose();
+ }
+
+ public void addEventListener(XEventListener listener) {}
+
+ public void removeEventListener(XEventListener listener) {}
+
+ public com.sun.star.beans.XPropertySetInfo getPropertySetInfo() {
+ return prop.getPropertySetInfo();
+ }
+
+ public void setPropertyValue(String propertyName, Object value)
+ throws UnknownPropertyException, PropertyVetoException,
+ com.sun.star.lang.IllegalArgumentException, WrappedTargetException
+ {
+ prop.setPropertyValue(propertyName, value);
+ }
+
+ public Object getPropertyValue(String propertyName)
+ throws UnknownPropertyException, WrappedTargetException
+ {
+ return prop.getPropertyValue(propertyName);
+ }
+
+ public void addPropertyChangeListener(
+ String propertyName, XPropertyChangeListener listener)
+ throws UnknownPropertyException, WrappedTargetException
+ {
+ prop.addPropertyChangeListener(propertyName, listener);
+ }
+
+ public void removePropertyChangeListener(
+ String propertyName, XPropertyChangeListener listener)
+ throws UnknownPropertyException, WrappedTargetException
+ {
+ prop.removePropertyChangeListener(propertyName, listener);
+ }
+
+ public void addVetoableChangeListener(
+ String propertyName, XVetoableChangeListener listener)
+ throws UnknownPropertyException, WrappedTargetException
+ {
+ prop.addVetoableChangeListener(propertyName, listener);
+ }
+
+ public void removeVetoableChangeListener(
+ String propertyName, XVetoableChangeListener listener)
+ throws UnknownPropertyException, WrappedTargetException
+ {
+ prop.removeVetoableChangeListener(propertyName, listener);
+ }
+
+ public void setFastPropertyValue(int handle, Object value)
+ throws UnknownPropertyException, PropertyVetoException,
+ com.sun.star.lang.IllegalArgumentException, WrappedTargetException
+ {
+ prop.setFastPropertyValue(handle, value);
+ }
+
+ public Object getFastPropertyValue(int handle)
+ throws UnknownPropertyException, WrappedTargetException
+ {
+ return prop.getFastPropertyValue(handle);
+ }
+
+ public PropertyValue[] getPropertyValues() {
+ return prop.getPropertyValues();
+ }
+
+ public void setPropertyValues(PropertyValue[] props)
+ throws UnknownPropertyException, PropertyVetoException,
+ com.sun.star.lang.IllegalArgumentException, WrappedTargetException
+ {
+ prop.setPropertyValues(props);
+ }
+
+ private final PropertySetMixin prop = new PropertySetMixin(
+ context, this, new Type(XComponent.class), null);
+ }
+
+ private final class Full extends WeakBase
+ implements XTest3, XPropertySet, XFastPropertySet, XPropertyAccess
+ {
+ public Full() {}
+
+ public synchronized int getFirst() {
+ return a1;
+ }
+
+ public void setFirst(int value) {
+ prop.prepareSet("First", null);
+ synchronized (this) {
+ a1 = value;
+ }
+ }
+
+ public synchronized Ambiguous getSecond()
+ throws UnknownPropertyException
+ {
+ return a2;
+ }
+
+ public void setSecond(Ambiguous value)
+ throws PropertyVetoException, UnknownPropertyException
+ {
+ PropertySetMixin.BoundListeners l
+ = new PropertySetMixin.BoundListeners();
+ prop.prepareSet(
+ "Second", Any.VOID,
+ (((Optional) ((Defaulted) value.Value).Value).IsPresent
+ ? ((Optional) ((Defaulted) value.Value).Value).Value
+ : Any.VOID),
+ l);
+ synchronized (this) {
+ a2 = value;
+ }
+ l.notifyListeners();
+ }
+
+ public int getThird() throws UnknownPropertyException {
+ throw new UnknownPropertyException("Third", this);
+ }
+
+ public void setThird(int value) throws UnknownPropertyException {
+ throw new UnknownPropertyException("Third", this);
+ }
+
+ public int getFourth() throws UnknownPropertyException {
+ throw new UnknownPropertyException("Fourth", this);
+ }
+
+ public void setFourth(int value) throws UnknownPropertyException {
+ throw new UnknownPropertyException("Fourth", this);
+ }
+
+ public com.sun.star.beans.XPropertySetInfo getPropertySetInfo() {
+ return prop.getPropertySetInfo();
+ }
+
+ public void setPropertyValue(String propertyName, Object value)
+ throws UnknownPropertyException, PropertyVetoException,
+ com.sun.star.lang.IllegalArgumentException, WrappedTargetException
+ {
+ prop.setPropertyValue(propertyName, value);
+ }
+
+ public Object getPropertyValue(String propertyName)
+ throws UnknownPropertyException, WrappedTargetException
+ {
+ return prop.getPropertyValue(propertyName);
+ }
+
+ public void addPropertyChangeListener(
+ String propertyName, XPropertyChangeListener listener)
+ throws UnknownPropertyException, WrappedTargetException
+ {
+ prop.addPropertyChangeListener(propertyName, listener);
+ }
+
+ public void removePropertyChangeListener(
+ String propertyName, XPropertyChangeListener listener)
+ throws UnknownPropertyException, WrappedTargetException
+ {
+ prop.removePropertyChangeListener(propertyName, listener);
+ }
+
+ public void addVetoableChangeListener(
+ String propertyName, XVetoableChangeListener listener)
+ throws UnknownPropertyException, WrappedTargetException
+ {
+ prop.addVetoableChangeListener(propertyName, listener);
+ }
+
+ public void removeVetoableChangeListener(
+ String propertyName, XVetoableChangeListener listener)
+ throws UnknownPropertyException, WrappedTargetException
+ {
+ prop.removeVetoableChangeListener(propertyName, listener);
+ }
+
+ public void setFastPropertyValue(int handle, Object value)
+ throws UnknownPropertyException, PropertyVetoException,
+ com.sun.star.lang.IllegalArgumentException, WrappedTargetException
+ {
+ prop.setFastPropertyValue(handle, value);
+ }
+
+ public Object getFastPropertyValue(int handle)
+ throws UnknownPropertyException, WrappedTargetException
+ {
+ return prop.getFastPropertyValue(handle);
+ }
+
+ public PropertyValue[] getPropertyValues() {
+ return prop.getPropertyValues();
+ }
+
+ public void setPropertyValues(PropertyValue[] props)
+ throws UnknownPropertyException, PropertyVetoException,
+ com.sun.star.lang.IllegalArgumentException, WrappedTargetException
+ {
+ prop.setPropertyValues(props);
+ }
+
+ private final PropertySetMixin prop = new PropertySetMixin(
+ context, this, new Type(XTest3.class), new String[] { "Third" });
+
+ private int a1 = 0;
+ private Ambiguous a2 = new Ambiguous(
+ new Defaulted(new Optional(), true), false);
+ }
+
+ private final XComponentContext context;
+}
diff --git a/cppuhelper/qa/propertysetmixin/comp_propertysetmixin.cxx b/cppuhelper/qa/propertysetmixin/comp_propertysetmixin.cxx
new file mode 100644
index 000000000..62cbd19bb
--- /dev/null
+++ b/cppuhelper/qa/propertysetmixin/comp_propertysetmixin.cxx
@@ -0,0 +1,406 @@
+/* -*- 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 <test/cppuhelper/propertysetmixin/XSupplier.hpp>
+#include <test/cppuhelper/propertysetmixin/XTest3.hpp>
+
+#include <com/sun/star/beans/Ambiguous.hpp>
+#include <com/sun/star/beans/Defaulted.hpp>
+#include <com/sun/star/beans/Optional.hpp>
+#include <com/sun/star/beans/PropertyVetoException.hpp>
+#include <com/sun/star/beans/UnknownPropertyException.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <cppuhelper/propertysetmixin.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/implementationentry.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/weak.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Type.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <osl/mutex.hxx>
+#include <rtl/ustring.h>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+
+namespace com::sun::star {
+ class XEventListener;
+} } }
+
+namespace {
+
+class Empty1:
+ public cppu::OWeakObject, public css::lang::XComponent,
+ public cppu::PropertySetMixin< css::lang::XComponent >
+{
+public:
+ explicit Empty1(
+ css::uno::Reference< css::uno::XComponentContext > const & context):
+ cppu::PropertySetMixin< css::lang::XComponent >(
+ context, static_cast< Implements >(0),
+ css::uno::Sequence< OUString >())
+ {}
+
+ virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const & type)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL acquire() throw () { OWeakObject::acquire(); }
+
+ virtual void SAL_CALL release() throw () { OWeakObject::release(); }
+
+ virtual void SAL_CALL dispose() throw (css::uno::RuntimeException) {
+ cppu::PropertySetMixin< css::lang::XComponent >::dispose();
+ }
+
+ virtual void SAL_CALL addEventListener(
+ css::uno::Reference< css::lang::XEventListener > const &)
+ throw (css::uno::RuntimeException)
+ {}
+
+ virtual void SAL_CALL removeEventListener(
+ css::uno::Reference< css::lang::XEventListener > const &)
+ throw (css::uno::RuntimeException)
+ {}
+
+private:
+ Empty1(Empty1 &); // not defined
+ void operator =(Empty1 &); // not defined
+
+ virtual ~Empty1() {}
+};
+
+css::uno::Any Empty1::queryInterface(css::uno::Type const & type)
+ throw (css::uno::RuntimeException)
+{
+ css::uno::Any a(OWeakObject::queryInterface(type));
+ if (a.hasValue()) {
+ return a;
+ }
+ a = cppu::queryInterface(
+ type, static_cast< css::lang::XComponent * >(this));
+ return a.hasValue()
+ ? a
+ : cppu::PropertySetMixin< css::lang::XComponent >::queryInterface(
+ type);
+}
+
+class Empty2:
+ public cppu::OWeakObject, public css::lang::XComponent,
+ public cppu::PropertySetMixin< css::lang::XComponent >
+{
+public:
+ explicit Empty2(
+ css::uno::Reference< css::uno::XComponentContext > const & context):
+ cppu::PropertySetMixin< css::lang::XComponent >(
+ context,
+ static_cast< Implements >(
+ IMPLEMENTS_PROPERTY_SET | IMPLEMENTS_FAST_PROPERTY_SET
+ | IMPLEMENTS_PROPERTY_ACCESS),
+ css::uno::Sequence< OUString >())
+ {}
+
+ virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const & type)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL acquire() throw () { OWeakObject::acquire(); }
+
+ virtual void SAL_CALL release() throw () { OWeakObject::release(); }
+
+ virtual void SAL_CALL dispose() throw (css::uno::RuntimeException) {
+ cppu::PropertySetMixin< css::lang::XComponent >::dispose();
+ }
+
+ virtual void SAL_CALL addEventListener(
+ css::uno::Reference< css::lang::XEventListener > const &)
+ throw (css::uno::RuntimeException)
+ {}
+
+ virtual void SAL_CALL removeEventListener(
+ css::uno::Reference< css::lang::XEventListener > const &)
+ throw (css::uno::RuntimeException)
+ {}
+
+private:
+ Empty2(Empty2 &); // not defined
+ void operator =(Empty2 &); // not defined
+
+ virtual ~Empty2() {}
+};
+
+css::uno::Any Empty2::queryInterface(css::uno::Type const & type)
+ throw (css::uno::RuntimeException)
+{
+ css::uno::Any a(OWeakObject::queryInterface(type));
+ if (a.hasValue()) {
+ return a;
+ }
+ a = cppu::queryInterface(
+ type, static_cast< css::lang::XComponent * >(this));
+ return a.hasValue()
+ ? a
+ : cppu::PropertySetMixin< css::lang::XComponent >::queryInterface(
+ type);
+}
+
+css::uno::Sequence< OUString > sequenceThird() {
+ css::uno::Sequence<OUString> s { OUString("Third") };
+ return s;
+}
+
+class Full:
+ public cppu::OWeakObject, public test::cppuhelper::propertysetmixin::XTest3,
+ public cppu::PropertySetMixin<
+ test::cppuhelper::propertysetmixin::XTest3 >
+{
+public:
+ explicit Full(
+ css::uno::Reference< css::uno::XComponentContext > const & context):
+ cppu::PropertySetMixin<
+ test::cppuhelper::propertysetmixin::XTest3 >(
+ context,
+ static_cast< Implements >(
+ IMPLEMENTS_PROPERTY_SET | IMPLEMENTS_FAST_PROPERTY_SET
+ | IMPLEMENTS_PROPERTY_ACCESS),
+ sequenceThird()),
+ m_a1(0),
+ m_a2(
+ css::beans::Defaulted< css::beans::Optional< sal_Int32 > >(
+ css::beans::Optional< sal_Int32 >(), true),
+ false)
+ {}
+
+ virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const & type)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL acquire() throw () { OWeakObject::acquire(); }
+
+ virtual void SAL_CALL release() throw () { OWeakObject::release(); }
+
+ virtual sal_Int32 SAL_CALL getFirst() throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL setFirst(sal_Int32 value)
+ throw (css::uno::RuntimeException);
+
+ virtual
+ css::beans::Ambiguous<
+ css::beans::Defaulted< css::beans::Optional< sal_Int32 > > >
+ SAL_CALL getSecond()
+ throw (
+ css::beans::UnknownPropertyException, css::uno::RuntimeException);
+
+ virtual void SAL_CALL setSecond(
+ css::beans::Ambiguous<
+ css::beans::Defaulted< css::beans::Optional< ::sal_Int32 > > > const &
+ value)
+ throw (
+ css::beans::PropertyVetoException,
+ css::beans::UnknownPropertyException, css::uno::RuntimeException);
+
+ virtual sal_Int32 SAL_CALL getThird()
+ throw (
+ css::beans::UnknownPropertyException, css::uno::RuntimeException);
+
+ virtual void SAL_CALL setThird(sal_Int32 value)
+ throw (
+ css::beans::UnknownPropertyException, css::uno::RuntimeException);
+
+ virtual sal_Int32 SAL_CALL getFourth()
+ throw (
+ css::beans::UnknownPropertyException, css::uno::RuntimeException);
+
+ virtual void SAL_CALL setFourth(sal_Int32 value)
+ throw (
+ css::beans::UnknownPropertyException, css::uno::RuntimeException);
+
+private:
+ Full(Full &); // not defined
+ void operator =(Full &); // not defined
+
+ virtual ~Full() {}
+
+ osl::Mutex m_mutex;
+ sal_Int32 m_a1;
+ css::beans::Ambiguous<
+ css::beans::Defaulted< css::beans::Optional< sal_Int32 > > > m_a2;
+};
+
+css::uno::Any Full::queryInterface(css::uno::Type const & type)
+ throw (css::uno::RuntimeException)
+{
+ css::uno::Any a(OWeakObject::queryInterface(type));
+ if (a.hasValue()) {
+ return a;
+ }
+ a = cppu::queryInterface(
+ type,
+ static_cast< test::cppuhelper::propertysetmixin::XTest3 * >(this));
+ return a.hasValue()
+ ? a
+ : (cppu::PropertySetMixin<
+ test::cppuhelper::propertysetmixin::XTest3 >::queryInterface(
+ type));
+}
+
+sal_Int32 Full::getFirst() throw (css::uno::RuntimeException) {
+ osl::MutexGuard g(m_mutex);
+ return m_a1;
+}
+
+void Full::setFirst(sal_Int32 value) throw (css::uno::RuntimeException) {
+ prepareSet(
+ OUString("First"), css::uno::Any(),
+ css::uno::Any(), 0);
+ osl::MutexGuard g(m_mutex);
+ m_a1 = value;
+}
+
+css::beans::Ambiguous<
+ css::beans::Defaulted< css::beans::Optional< sal_Int32 > > >
+Full::getSecond()
+ throw (css::beans::UnknownPropertyException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(m_mutex);
+ return m_a2;
+}
+
+void Full::setSecond(
+ css::beans::Ambiguous<
+ css::beans::Defaulted< css::beans::Optional< ::sal_Int32 > > > const &
+ value)
+ throw (
+ css::beans::PropertyVetoException, css::beans::UnknownPropertyException,
+ css::uno::RuntimeException)
+{
+ css::uno::Any v;
+ if (value.Value.Value.IsPresent) {
+ v <<= value.Value.Value.Value;
+ }
+ BoundListeners l;
+ prepareSet(
+ OUString("Second"), css::uno::Any(),
+ v, &l);
+ {
+ osl::MutexGuard g(m_mutex);
+ m_a2 = value;
+ }
+ l.notify();
+}
+
+sal_Int32 Full::getThird()
+ throw (css::beans::UnknownPropertyException, css::uno::RuntimeException)
+{
+ throw css::beans::UnknownPropertyException(
+ OUString("Third"),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+void Full::setThird(sal_Int32)
+ throw (css::beans::UnknownPropertyException, css::uno::RuntimeException)
+{
+ throw css::beans::UnknownPropertyException(
+ OUString("Third"),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+sal_Int32 Full::getFourth()
+ throw (css::beans::UnknownPropertyException, css::uno::RuntimeException)
+{
+ throw css::beans::UnknownPropertyException(
+ OUString("Fourth"),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+void Full::setFourth(sal_Int32)
+ throw (css::beans::UnknownPropertyException, css::uno::RuntimeException)
+{
+ throw css::beans::UnknownPropertyException(
+ OUString("Fourth"),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+class Supplier:
+ public cppu::WeakImplHelper<
+ test::cppuhelper::propertysetmixin::XSupplier >
+{
+public:
+ explicit Supplier(
+ css::uno::Reference< css::uno::XComponentContext > const & context):
+ m_context(context) {}
+
+ virtual css::uno::Reference< css::lang::XComponent > SAL_CALL getEmpty1()
+ throw (css::uno::RuntimeException)
+ { return new Empty1(m_context); }
+
+ virtual css::uno::Reference< css::lang::XComponent > SAL_CALL getEmpty2()
+ throw (css::uno::RuntimeException)
+ { return new Empty2(m_context); }
+
+ virtual css::uno::Reference< test::cppuhelper::propertysetmixin::XTest3 >
+ SAL_CALL getFull() throw (css::uno::RuntimeException)
+ { return new Full(m_context); }
+
+private:
+ Supplier(Supplier &); // not defined
+ void operator =(Supplier &); // not defined
+
+ virtual ~Supplier() {}
+
+ css::uno::Reference< css::uno::XComponentContext > m_context;
+};
+
+css::uno::Reference< css::uno::XInterface > SAL_CALL create(
+ css::uno::Reference< css::uno::XComponentContext > const & context)
+{
+ return static_cast< cppu::OWeakObject * >(new Supplier(context));
+}
+
+OUString SAL_CALL getImplementationName() {
+ return OUString(
+ "test.cppuhelper.propertysetmixin.comp.CppSupplier");
+}
+
+css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames()
+{
+ return { "test.cppuhelper.propertysetmixin.CppSupplier" };
+}
+
+cppu::ImplementationEntry entries[] = {
+ { &create, &getImplementationName, &getSupportedServiceNames,
+ &cppu::createSingleComponentFactory, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 } };
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL mixin_component_getFactory(
+ char const * implName, void * serviceManager, void * registryKey)
+{
+ return cppu::component_getFactoryHelper(
+ implName, serviceManager, registryKey, entries);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/qa/propertysetmixin/manifest b/cppuhelper/qa/propertysetmixin/manifest
new file mode 100644
index 000000000..168f4bc19
--- /dev/null
+++ b/cppuhelper/qa/propertysetmixin/manifest
@@ -0,0 +1,2 @@
+Manifest-Version: 1.0
+RegistrationClassName: test.cppuhelper.propertysetmixin.comp.JavaSupplier
diff --git a/cppuhelper/qa/propertysetmixin/qa_propertysetmixin.cpp.component b/cppuhelper/qa/propertysetmixin/qa_propertysetmixin.cpp.component
new file mode 100644
index 000000000..eebe9b725
--- /dev/null
+++ b/cppuhelper/qa/propertysetmixin/qa_propertysetmixin.cpp.component
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ prefix="mixin" xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="test.cppuhelper.propertysetmixin.comp.CppSupplier">
+ <service name="test.cppuhelper.propertysetmixin.CppSupplier"/>
+ </implementation>
+</component>
diff --git a/cppuhelper/qa/propertysetmixin/qa_propertysetmixin.java.component b/cppuhelper/qa/propertysetmixin/qa_propertysetmixin.java.component
new file mode 100644
index 000000000..887dfe6f0
--- /dev/null
+++ b/cppuhelper/qa/propertysetmixin/qa_propertysetmixin.java.component
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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 .
+ -->
+
+<component loader="com.sun.star.loader.Java2"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="test.cppuhelper.propertysetmixin.comp.JavaSupplier">
+ <service name="test.cppuhelper.propertysetmixin.JavaSupplier"/>
+ </implementation>
+</component>
diff --git a/cppuhelper/qa/propertysetmixin/test_propertysetmixin.cxx b/cppuhelper/qa/propertysetmixin/test_propertysetmixin.cxx
new file mode 100644
index 000000000..d6679dae5
--- /dev/null
+++ b/cppuhelper/qa/propertysetmixin/test_propertysetmixin.cxx
@@ -0,0 +1,639 @@
+/* -*- 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 <test/cppuhelper/propertysetmixin/CppSupplier.hpp>
+#include <test/cppuhelper/propertysetmixin/JavaSupplier.hpp>
+#include <test/cppuhelper/propertysetmixin/XSupplier.hpp>
+#include <test/cppuhelper/propertysetmixin/XTest3.hpp>
+
+#include <com/sun/star/beans/Ambiguous.hpp>
+#include <com/sun/star/beans/Defaulted.hpp>
+#include <com/sun/star/beans/Optional.hpp>
+#include <com/sun/star/beans/Property.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/PropertyChangeEvent.hpp>
+#include <com/sun/star/beans/PropertyState.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/PropertyVetoException.hpp>
+#include <com/sun/star/beans/UnknownPropertyException.hpp>
+#include <com/sun/star/beans/XFastPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyAccess.hpp>
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/beans/XVetoableChangeListener.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Type.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <cppuhelper/bootstrap.hxx>
+#include <cppuhelper/implbase.hxx>
+#include "cppunit/TestAssert.h"
+#include "cppunit/TestFixture.h"
+#include "cppunit/extensions/HelperMacros.h"
+#include "cppunit/plugin/TestPlugIn.h"
+#include <osl/mutex.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/string.h>
+#include <rtl/textenc.h>
+#include <rtl/ustring.h>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+
+#include <limits>
+#include <ostream>
+
+namespace com::sun::star {
+ struct EventObject;
+} } }
+
+namespace {
+
+std::ostream & operator <<(std::ostream & out, OUString const & value) {
+ return out << OUStringToOString(value, RTL_TEXTENCODING_UTF8).getStr();
+}
+
+std::ostream & operator <<(std::ostream & out, css::uno::Type const & value) {
+ return out << "com::sun::star::uno::Type[" << value.getTypeName() << ']';
+}
+
+std::ostream & operator <<(std::ostream & out, css::uno::Any const & value) {
+ return
+ out << "com::sun::star::uno::Any[" << value.getValueType() << ", ...]";
+}
+
+class BoundListener:
+ public cppu::WeakImplHelper< css::beans::XPropertyChangeListener >
+{
+public:
+ BoundListener(): m_count(0) {}
+
+ int count() const {
+ osl::MutexGuard g(m_mutex);
+ return m_count;
+ }
+
+ virtual void SAL_CALL disposing(css::lang::EventObject const &)
+ throw (css::uno::RuntimeException)
+ {
+ osl::MutexGuard g(m_mutex);
+ CPPUNIT_ASSERT(m_count < std::numeric_limits< int >::max());
+ ++m_count;
+ }
+
+ virtual void SAL_CALL propertyChange(
+ css::beans::PropertyChangeEvent const &)
+ throw (css::uno::RuntimeException)
+ { CPPUNIT_FAIL("BoundListener::propertyChange called"); }
+
+private:
+ BoundListener(BoundListener &); // not defined
+ void operator =(BoundListener &); // not defined
+
+ virtual ~BoundListener() {}
+
+ mutable osl::Mutex m_mutex;
+ int m_count;
+};
+
+class VetoListener:
+ public cppu::WeakImplHelper< css::beans::XVetoableChangeListener >
+{
+public:
+ VetoListener(): m_count(0) {}
+
+ int count() const {
+ osl::MutexGuard g(m_mutex);
+ return m_count;
+ }
+
+ virtual void SAL_CALL disposing(css::lang::EventObject const &)
+ throw (css::uno::RuntimeException)
+ {
+ osl::MutexGuard g(m_mutex);
+ CPPUNIT_ASSERT(m_count < std::numeric_limits< int >::max());
+ ++m_count;
+ }
+
+ virtual void SAL_CALL vetoableChange(
+ css::beans::PropertyChangeEvent const &)
+ throw (css::beans::PropertyVetoException, css::uno::RuntimeException)
+ { CPPUNIT_FAIL("VetoListener::vetoableChange called"); }
+
+private:
+ VetoListener(VetoListener &); // not defined
+ void operator =(VetoListener &); // not defined
+
+ virtual ~VetoListener() {}
+
+ mutable osl::Mutex m_mutex;
+ int m_count;
+};
+
+class Test: public CppUnit::TestFixture {
+public:
+ virtual void setUp();
+
+ virtual void tearDown();
+
+ void testCppEmpty1() { testEmpty1(getCppSupplier()); }
+
+ void testCppEmpty2() { testEmpty2(getCppSupplier()); }
+
+ void testCppFull() { testFull(getCppSupplier()); }
+
+ void testJavaEmpty1() { testEmpty1(getJavaSupplier()); }
+
+ void testJavaEmpty2() { testEmpty2(getJavaSupplier()); }
+
+ void testJavaFull() { testFull(getJavaSupplier()); }
+
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testCppEmpty1);
+ CPPUNIT_TEST(testCppEmpty2);
+ CPPUNIT_TEST(testCppFull);
+ CPPUNIT_TEST(testJavaEmpty1);
+ CPPUNIT_TEST(testJavaEmpty2);
+ CPPUNIT_TEST(testJavaFull);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ css::uno::Reference< test::cppuhelper::propertysetmixin::XSupplier >
+ getCppSupplier() const;
+
+ css::uno::Reference< test::cppuhelper::propertysetmixin::XSupplier >
+ getJavaSupplier() const;
+
+ void testEmpty1(
+ css::uno::Reference< test::cppuhelper::propertysetmixin::XSupplier >
+ const & supplier) const;
+
+ void testEmpty2(
+ css::uno::Reference< test::cppuhelper::propertysetmixin::XSupplier >
+ const & supplier) const;
+
+ void testFull(
+ css::uno::Reference< test::cppuhelper::propertysetmixin::XSupplier >
+ const & supplier) const;
+
+ css::uno::Reference< css::uno::XComponentContext > m_context;
+};
+
+void Test::setUp() {
+ m_context = cppu::defaultBootstrap_InitialComponentContext();
+ CPPUNIT_ASSERT(m_context.is());
+}
+
+void Test::tearDown() {
+ css::uno::Reference< css::lang::XComponent >(
+ m_context, css::uno::UNO_QUERY_THROW)->dispose();
+}
+
+css::uno::Reference< test::cppuhelper::propertysetmixin::XSupplier >
+Test::getCppSupplier() const
+{
+ return test::cppuhelper::propertysetmixin::CppSupplier::create(m_context);
+}
+
+css::uno::Reference< test::cppuhelper::propertysetmixin::XSupplier >
+Test::getJavaSupplier() const
+{
+ return test::cppuhelper::propertysetmixin::JavaSupplier::create(m_context);
+}
+
+void Test::testEmpty1(
+ css::uno::Reference< test::cppuhelper::propertysetmixin::XSupplier >
+ const & supplier) const
+{
+ css::uno::Reference< css::lang::XComponent > empty1(
+ supplier->getEmpty1(), css::uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(
+ !css::uno::Reference< css::beans::XPropertySet >(
+ empty1, css::uno::UNO_QUERY).is());
+ CPPUNIT_ASSERT(
+ !css::uno::Reference< css::beans::XFastPropertySet >(
+ empty1, css::uno::UNO_QUERY).is());
+ CPPUNIT_ASSERT(
+ !css::uno::Reference< css::beans::XPropertyAccess >(
+ empty1, css::uno::UNO_QUERY).is());
+ empty1->dispose();
+}
+
+void Test::testEmpty2(
+ css::uno::Reference< test::cppuhelper::propertysetmixin::XSupplier >
+ const & supplier) const
+{
+ css::uno::Reference< css::lang::XComponent > empty2(
+ supplier->getEmpty2(), css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::beans::XPropertySet > empty2p(
+ empty2, css::uno::UNO_QUERY);
+ CPPUNIT_ASSERT(empty2p.is());
+ css::uno::Reference< css::beans::XPropertySetInfo > info(
+ empty2p->getPropertySetInfo());
+ CPPUNIT_ASSERT(info.is());
+ CPPUNIT_ASSERT_EQUAL(
+ static_cast< sal_Int32 >(0), info->getProperties().getLength());
+ try {
+ info->getPropertyByName(
+ OUString("any"));
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ CPPUNIT_ASSERT(
+ !info->hasPropertyByName(
+ OUString("any")));
+ try {
+ empty2p->setPropertyValue(
+ OUString("any"), css::uno::Any());
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ try {
+ empty2p->getPropertyValue(
+ OUString("any"));
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ rtl::Reference boundListener1(new BoundListener);
+ empty2p->addPropertyChangeListener(OUString(), boundListener1.get());
+ empty2p->addPropertyChangeListener(OUString(), boundListener1.get());
+ rtl::Reference boundListener2(new BoundListener);
+ empty2p->removePropertyChangeListener(
+ OUString(), boundListener2.get());
+ rtl::Reference vetoListener1(new VetoListener);
+ empty2p->addVetoableChangeListener(OUString(), vetoListener1.get());
+ empty2p->addVetoableChangeListener(OUString(), vetoListener1.get());
+ rtl::Reference vetoListener2(new VetoListener);
+ empty2p->addVetoableChangeListener(OUString(), vetoListener2.get());
+ empty2p->removeVetoableChangeListener(OUString(), vetoListener2.get());
+ css::uno::Reference< css::beans::XFastPropertySet > empty2f(
+ empty2, css::uno::UNO_QUERY);
+ CPPUNIT_ASSERT(empty2f.is());
+ try {
+ empty2f->setFastPropertyValue(-1, css::uno::Any());
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ try {
+ empty2f->setFastPropertyValue(0, css::uno::Any());
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ try {
+ empty2f->getFastPropertyValue(-1);
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ try {
+ empty2f->getFastPropertyValue(0);
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ css::uno::Reference< css::beans::XPropertyAccess > empty2a(
+ empty2, css::uno::UNO_QUERY);
+ CPPUNIT_ASSERT(empty2a.is());
+ CPPUNIT_ASSERT_EQUAL(
+ static_cast< sal_Int32 >(0), empty2a->getPropertyValues().getLength());
+ empty2a->setPropertyValues(
+ css::uno::Sequence< css::beans::PropertyValue >());
+ css::uno::Sequence< css::beans::PropertyValue > vs(2);
+ vs[0].Name = OUString("any1");
+ vs[0].Handle = -1;
+ vs[0].State = css::beans::PropertyState_DIRECT_VALUE;
+ vs[0].Name = OUString("any2");
+ vs[0].Handle = -1;
+ vs[0].State = css::beans::PropertyState_DIRECT_VALUE;
+ try {
+ empty2a->setPropertyValues(vs);
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ CPPUNIT_ASSERT_EQUAL(0, boundListener1->count());
+ CPPUNIT_ASSERT_EQUAL(0, boundListener2->count());
+ CPPUNIT_ASSERT_EQUAL(0, vetoListener1->count());
+ CPPUNIT_ASSERT_EQUAL(0, vetoListener2->count());
+ empty2->dispose();
+ CPPUNIT_ASSERT_EQUAL(2, boundListener1->count());
+ CPPUNIT_ASSERT_EQUAL(0, boundListener2->count());
+ CPPUNIT_ASSERT_EQUAL(2, vetoListener1->count());
+ CPPUNIT_ASSERT_EQUAL(0, vetoListener2->count());
+ empty2p->removePropertyChangeListener(
+ OUString(), boundListener1.get());
+ empty2p->removePropertyChangeListener(
+ OUString(), boundListener2.get());
+ empty2p->removeVetoableChangeListener(OUString(), vetoListener1.get());
+ empty2p->removeVetoableChangeListener(OUString(), vetoListener2.get());
+ empty2p->addPropertyChangeListener(OUString(), boundListener1.get());
+ empty2p->addPropertyChangeListener(OUString(), boundListener2.get());
+ empty2p->addVetoableChangeListener(OUString(), vetoListener1.get());
+ empty2p->addVetoableChangeListener(OUString(), vetoListener2.get());
+ try {
+ empty2p->addPropertyChangeListener(
+ OUString(),
+ css::uno::Reference< css::beans::XPropertyChangeListener >());
+ } catch (css::uno::RuntimeException &) {}
+ try {
+ empty2p->addVetoableChangeListener(
+ OUString(),
+ css::uno::Reference< css::beans::XVetoableChangeListener >());
+ } catch (css::uno::RuntimeException &) {}
+ CPPUNIT_ASSERT_EQUAL(3, boundListener1->count());
+ CPPUNIT_ASSERT_EQUAL(1, boundListener2->count());
+ CPPUNIT_ASSERT_EQUAL(3, vetoListener1->count());
+ CPPUNIT_ASSERT_EQUAL(1, vetoListener2->count());
+}
+
+void Test::testFull(
+ css::uno::Reference< test::cppuhelper::propertysetmixin::XSupplier >
+ const & supplier) const
+{
+ css::uno::Reference< test::cppuhelper::propertysetmixin::XTest3 > full(
+ supplier->getFull(), css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::beans::XPropertySet > fullp(
+ full, css::uno::UNO_QUERY);
+ CPPUNIT_ASSERT(fullp.is());
+ css::uno::Reference< css::beans::XPropertySetInfo > info(
+ fullp->getPropertySetInfo());
+ CPPUNIT_ASSERT(info.is());
+ CPPUNIT_ASSERT_EQUAL(
+ static_cast< sal_Int32 >(3), info->getProperties().getLength());
+ css::beans::Property prop(
+ info->getPropertyByName(
+ OUString("First")));
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("First"), prop.Name);
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int32 >(0), prop.Handle);
+ CPPUNIT_ASSERT_EQUAL(cppu::UnoType<sal_Int32>::get(), prop.Type);
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int16 >(0), prop.Attributes);
+ prop = info->getPropertyByName(
+ OUString("Second"));
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("Second"), prop.Name);
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int32 >(1), prop.Handle);
+ CPPUNIT_ASSERT_EQUAL(cppu::UnoType<sal_Int32>::get(), prop.Type);
+ CPPUNIT_ASSERT_EQUAL(
+ static_cast< sal_Int16 >(
+ css::beans::PropertyAttribute::MAYBEVOID
+ | css::beans::PropertyAttribute::BOUND
+ | css::beans::PropertyAttribute::CONSTRAINED
+ | css::beans::PropertyAttribute::MAYBEAMBIGUOUS
+ | css::beans::PropertyAttribute::MAYBEDEFAULT
+ | css::beans::PropertyAttribute::OPTIONAL),
+ prop.Attributes);
+ try {
+ info->getPropertyByName(
+ OUString("Third"));
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ prop = info->getPropertyByName(
+ OUString("Fourth"));
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("Fourth"), prop.Name);
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int32 >(3), prop.Handle);
+ CPPUNIT_ASSERT_EQUAL(cppu::UnoType<sal_Int32>::get(), prop.Type);
+ CPPUNIT_ASSERT_EQUAL(
+ static_cast< sal_Int16 >(css::beans::PropertyAttribute::OPTIONAL),
+ prop.Attributes);
+ try {
+ info->getPropertyByName(
+ OUString("first"));
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ CPPUNIT_ASSERT(
+ info->hasPropertyByName(
+ OUString("First")));
+ CPPUNIT_ASSERT(
+ info->hasPropertyByName(
+ OUString("Second")));
+ CPPUNIT_ASSERT(
+ !info->hasPropertyByName(
+ OUString("Third")));
+ CPPUNIT_ASSERT(
+ info->hasPropertyByName(
+ OUString("Fourth")));
+ CPPUNIT_ASSERT(
+ !info->hasPropertyByName(
+ OUString("first")));
+ CPPUNIT_ASSERT_EQUAL(
+ css::uno::Any(static_cast< sal_Int32 >(0)),
+ fullp->getPropertyValue(
+ OUString("First")));
+ fullp->setPropertyValue(
+ OUString("First"),
+ css::uno::Any(static_cast< sal_Int32 >(-100)));
+ CPPUNIT_ASSERT_EQUAL(
+ css::uno::Any(static_cast< sal_Int32 >(-100)),
+ fullp->getPropertyValue(
+ OUString("First")));
+ css::uno::Any voidAny;
+ CPPUNIT_ASSERT_EQUAL(
+ voidAny,
+ fullp->getPropertyValue(
+ OUString("Second")));
+ fullp->setPropertyValue(
+ OUString("Second"),
+ css::uno::Any(static_cast< sal_Int32 >(100)));
+ CPPUNIT_ASSERT_EQUAL(
+ css::uno::Any(static_cast< sal_Int32 >(100)),
+ fullp->getPropertyValue(
+ OUString("Second")));
+ CPPUNIT_ASSERT(full->getSecond().Value.Value.IsPresent);
+ CPPUNIT_ASSERT_EQUAL(
+ static_cast< sal_Int32 >(100), full->getSecond().Value.Value.Value);
+ CPPUNIT_ASSERT(!full->getSecond().Value.IsDefaulted);
+ CPPUNIT_ASSERT(!full->getSecond().IsAmbiguous);
+ fullp->setPropertyValue(
+ OUString("Second"),
+ css::uno::Any());
+ CPPUNIT_ASSERT_EQUAL(
+ voidAny,
+ fullp->getPropertyValue(
+ OUString("Second")));
+ CPPUNIT_ASSERT(!full->getSecond().Value.Value.IsPresent);
+ CPPUNIT_ASSERT(!full->getSecond().Value.IsDefaulted);
+ CPPUNIT_ASSERT(!full->getSecond().IsAmbiguous);
+ try {
+ fullp->setPropertyValue(
+ OUString("Third"),
+ css::uno::Any(static_cast< sal_Int32 >(100)));
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ try {
+ fullp->getPropertyValue(
+ OUString("Third"));
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ try {
+ fullp->setPropertyValue(
+ OUString("Fourth"),
+ css::uno::Any(static_cast< sal_Int32 >(100)));
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ try {
+ fullp->getPropertyValue(
+ OUString("Fourth"));
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ try {
+ fullp->setPropertyValue(
+ OUString("first"),
+ css::uno::Any());
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ try {
+ fullp->getPropertyValue(
+ OUString("first"));
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ css::uno::Reference< css::beans::XFastPropertySet > fullf(
+ full, css::uno::UNO_QUERY);
+ CPPUNIT_ASSERT(fullf.is());
+ CPPUNIT_ASSERT_EQUAL(
+ css::uno::Any(static_cast< sal_Int32 >(-100)),
+ fullf->getFastPropertyValue(0));
+ fullf->setFastPropertyValue(
+ 0, css::uno::Any(static_cast< sal_Int32 >(0)));
+ CPPUNIT_ASSERT_EQUAL(
+ css::uno::Any(static_cast< sal_Int32 >(0)),
+ fullf->getFastPropertyValue(0));
+ try {
+ fullf->getFastPropertyValue(-1);
+ } catch (css::beans::UnknownPropertyException &) {}
+ try {
+ fullf->setFastPropertyValue(-1, css::uno::Any());
+ } catch (css::beans::UnknownPropertyException &) {}
+ css::uno::Reference< css::beans::XPropertyAccess > fulla(
+ full, css::uno::UNO_QUERY);
+ CPPUNIT_ASSERT(fulla.is());
+ css::uno::Sequence< css::beans::PropertyValue > vs(
+ fulla->getPropertyValues());
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int32 >(2), vs.getLength());
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("First"), vs[0].Name);
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int32 >(0), vs[0].Handle);
+ CPPUNIT_ASSERT_EQUAL(
+ css::uno::Any(static_cast< sal_Int32 >(0)), vs[0].Value);
+ CPPUNIT_ASSERT_EQUAL(css::beans::PropertyState_DIRECT_VALUE, vs[0].State);
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("Second"), vs[1].Name);
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int32 >(1), vs[1].Handle);
+ CPPUNIT_ASSERT_EQUAL(voidAny, vs[1].Value);
+ CPPUNIT_ASSERT_EQUAL(css::beans::PropertyState_DIRECT_VALUE, vs[1].State);
+ vs[0].Value <<= static_cast< sal_Int32 >(-100);
+ vs[1].Value <<= static_cast< sal_Int32 >(100);
+ vs[1].State = css::beans::PropertyState_AMBIGUOUS_VALUE;
+ fulla->setPropertyValues(vs);
+ vs = fulla->getPropertyValues();
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_Int32 >(2), vs.getLength());
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("First"), vs[0].Name);
+ CPPUNIT_ASSERT_EQUAL(
+ css::uno::Any(static_cast< sal_Int32 >(-100)), vs[0].Value);
+ CPPUNIT_ASSERT_EQUAL(css::beans::PropertyState_DIRECT_VALUE, vs[0].State);
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("Second"), vs[1].Name);
+ CPPUNIT_ASSERT_EQUAL(
+ css::uno::Any(static_cast< sal_Int32 >(100)), vs[1].Value);
+ CPPUNIT_ASSERT_EQUAL(
+ css::beans::PropertyState_AMBIGUOUS_VALUE, vs[1].State);
+ CPPUNIT_ASSERT(full->getSecond().Value.Value.IsPresent);
+ CPPUNIT_ASSERT_EQUAL(
+ static_cast< sal_Int32 >(100), full->getSecond().Value.Value.Value);
+ CPPUNIT_ASSERT(!full->getSecond().Value.IsDefaulted);
+ CPPUNIT_ASSERT(full->getSecond().IsAmbiguous);
+ css::uno::Reference< css::beans::XPropertyChangeListener > boundListener(
+ new BoundListener);
+ fullp->addPropertyChangeListener(
+ OUString("First"), boundListener);
+ fullp->removePropertyChangeListener(
+ OUString("First"), boundListener);
+ fullp->addPropertyChangeListener(
+ OUString("Second"), boundListener);
+ fullp->removePropertyChangeListener(
+ OUString("Second"), boundListener);
+ try {
+ fullp->addPropertyChangeListener(
+ OUString("Third"),
+ boundListener);
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ try {
+ fullp->removePropertyChangeListener(
+ OUString("Third"),
+ boundListener);
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ fullp->addPropertyChangeListener(
+ OUString("Fourth"), boundListener);
+ fullp->removePropertyChangeListener(
+ OUString("Fourth"), boundListener);
+ try {
+ fullp->addPropertyChangeListener(
+ OUString("Fifth"),
+ boundListener);
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ try {
+ fullp->removePropertyChangeListener(
+ OUString("Fifth"),
+ boundListener);
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ css::uno::Reference< css::beans::XVetoableChangeListener > vetoListener(
+ new VetoListener);
+ fullp->addVetoableChangeListener(
+ OUString("First"), vetoListener);
+ fullp->removeVetoableChangeListener(
+ OUString("First"), vetoListener);
+ fullp->addVetoableChangeListener(
+ OUString("Second"), vetoListener);
+ fullp->removeVetoableChangeListener(
+ OUString("Second"), vetoListener);
+ try {
+ fullp->addVetoableChangeListener(
+ OUString("Third"),
+ vetoListener);
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ try {
+ fullp->removeVetoableChangeListener(
+ OUString("Third"),
+ vetoListener);
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ fullp->addVetoableChangeListener(
+ OUString("Fourth"), vetoListener);
+ fullp->removeVetoableChangeListener(
+ OUString("Fourth"), vetoListener);
+ try {
+ fullp->addVetoableChangeListener(
+ OUString("Fifth"),
+ vetoListener);
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+ try {
+ fullp->removeVetoableChangeListener(
+ OUString("Fifth"),
+ vetoListener);
+ CPPUNIT_FAIL("exception expected");
+ } catch (css::beans::UnknownPropertyException &) {}
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/qa/propertysetmixin/types.idl b/cppuhelper/qa/propertysetmixin/types.idl
new file mode 100644
index 000000000..ee1958032
--- /dev/null
+++ b/cppuhelper/qa/propertysetmixin/types.idl
@@ -0,0 +1,79 @@
+/* -*- 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 __testtools_servicetests_TestService1_idl__
+#define __testtools_servicetests_TestService1_idl__
+
+#include <com/sun/star/beans/Ambiguous.idl>
+#include <com/sun/star/beans/Defaulted.idl>
+#include <com/sun/star/beans/Optional.idl>
+#include <com/sun/star/beans/PropertyVetoException.idl>
+#include <com/sun/star/beans/UnknownPropertyException.idl>
+#include <com/sun/star/lang/XComponent.idl>
+#include <com/sun/star/uno/XInterface.idl>
+
+module test { module cppuhelper { module propertysetmixin {
+
+interface XTest1 {
+ [attribute] long First;
+};
+
+interface XTest2 {
+ [attribute, bound]
+ com::sun::star::beans::Ambiguous<
+ com::sun::star::beans::Defaulted<
+ com::sun::star::beans::Optional< long > > > Second
+ {
+ get raises (com::sun::star::beans::UnknownPropertyException);
+ set raises (
+ com::sun::star::beans::PropertyVetoException,
+ com::sun::star::beans::UnknownPropertyException);
+ };
+};
+
+interface XTest3 {
+ interface XTest1;
+ interface XTest2;
+ [attribute] long Third {
+ get raises (com::sun::star::beans::UnknownPropertyException);
+ set raises (com::sun::star::beans::UnknownPropertyException);
+ };
+ [attribute] long Fourth {
+ get raises (com::sun::star::beans::UnknownPropertyException);
+ set raises (com::sun::star::beans::UnknownPropertyException);
+ };
+};
+
+interface XSupplier {
+ com::sun::star::lang::XComponent getEmpty1();
+
+ com::sun::star::lang::XComponent getEmpty2();
+
+ XTest3 getFull();
+};
+
+service CppSupplier: XSupplier;
+
+service JavaSupplier: XSupplier;
+
+}; }; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/qa/sce/test_unourl.sce b/cppuhelper/qa/sce/test_unourl.sce
new file mode 100644
index 000000000..d937ca311
--- /dev/null
+++ b/cppuhelper/qa/sce/test_unourl.sce
@@ -0,0 +1 @@
+UnoUrl
diff --git a/cppuhelper/qa/unourl/cppu_unourl.cxx b/cppuhelper/qa/unourl/cppu_unourl.cxx
new file mode 100644
index 000000000..012617248
--- /dev/null
+++ b/cppuhelper/qa/unourl/cppu_unourl.cxx
@@ -0,0 +1,473 @@
+/* -*- 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/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <cppuhelper/unourl.hxx>
+#include <rtl/malformeduriexception.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+
+namespace cppu_unourl
+{
+ class UrlTest : public CppUnit::TestFixture
+ {
+ public:
+ void testDescriptorParsing()
+ {
+ struct Test
+ {
+ char const * pInput;
+ bool bValid;
+ };
+ static Test const aTests[]
+ = { { "", false },
+ { "abc", true },
+ { "Abc", true },
+ { "aBC", true },
+ { "ABC", true },
+ { "1abc", true },
+ { "123", true },
+ { "abc-1", false },
+ { "ab%63", false },
+ { "abc,", false },
+ { "abc,def=", true },
+ { "abc,Def=", true },
+ { "abc,DEF=", true },
+ { "abc,1def=", true },
+ { "abc,123=", true },
+ { "abc,def-1=", false },
+ { "abc,def", false },
+ { "abc,def=xxx,def=xxx", false },
+ { "abc,def=xxx,ghi=xxx", true },
+ { "abc,,def=xxx", false },
+ { "abc,def=xxx,,ghi=xxx", false },
+ { "abc,def=xxx,ghi=xxx,", false },
+ { "abc,def=%", true },
+ { "abc,def=%1", true },
+ { "abc,def=%00", true },
+ { "abc,def=%22", true },
+ { "abc,def=\"", true },
+ { "abc,def=%ed%a0%80", true } };
+ for (size_t i = 0; i < std::size(aTests); ++i)
+ {
+ bool bValid = false;
+ try
+ {
+ cppu::UnoUrlDescriptor aDescriptor(OUString::createFromAscii(
+ aTests[i].pInput));
+ (void)aDescriptor;
+ bValid = true;
+ }
+ catch (rtl::MalformedUriException &)
+ {}
+
+ if (aTests[i].bValid)
+ {
+ CPPUNIT_ASSERT_MESSAGE("Valid uri parsed as invalid", bValid);
+ }
+ else
+ {
+ CPPUNIT_ASSERT_MESSAGE("Invalid uri parsed as valid", !bValid);
+ }
+ }
+ }
+
+ void testDescriptorDescriptor()
+ {
+ struct Test
+ {
+ char const * pInput;
+ char const * pDescriptor;
+ };
+ static Test const aTests[]
+ = {{ "abc", "abc" },
+ { "Abc", "Abc" },
+ { "aBC", "aBC" },
+ { "ABC", "ABC" },
+ { "1abc", "1abc" },
+ { "123", "123" },
+ { "abc,def=", "abc,def=" },
+ { "abc,Def=", "abc,Def=" },
+ { "abc,DEF=", "abc,DEF=" },
+ { "abc,1def=", "abc,1def=" },
+ { "abc,123=", "abc,123=" },
+ { "abc,def=xxx,ghi=xxx", "abc,def=xxx,ghi=xxx" },
+ { "abc,def=%", "abc,def=%" },
+ { "abc,def=%1", "abc,def=%1" },
+ { "abc,def=%00", "abc,def=%00" },
+ { "abc,def=%22", "abc,def=%22" },
+ { "abc,def=\"", "abc,def=\"" },
+ { "abc,def=%ed%a0%80", "abc,def=%ed%a0%80" } };
+ for (size_t i = 0; i < std::size(aTests); ++i)
+ {
+ bool bValid = false;
+ OUString aDescriptor;
+ try
+ {
+ aDescriptor = cppu::UnoUrlDescriptor(OUString::createFromAscii(
+ aTests[i].pInput)).
+ getDescriptor();
+ bValid = true;
+ }
+ catch (rtl::MalformedUriException &)
+ {}
+
+ CPPUNIT_ASSERT_MESSAGE("Failed to parse URI", bValid);
+ CPPUNIT_ASSERT_MESSAGE("Failed to parse URI correctly",
+ aDescriptor.equalsAscii(
+ aTests[i].pDescriptor));
+ }
+ }
+
+
+ void testDescriptorName()
+ {
+ struct Test
+ {
+ char const * pInput;
+ char const * pName;
+ };
+ static Test const aTests[]
+ = { { "abc", "abc" },
+ { "Abc", "abc" },
+ { "aBC", "abc" },
+ { "ABC", "abc" },
+ { "1abc", "1abc" },
+ { "123", "123" },
+ { "abc,def=", "abc" },
+ { "abc,Def=", "abc" },
+ { "abc,DEF=", "abc" },
+ { "abc,1def=", "abc" },
+ { "abc,123=", "abc" },
+ { "abc,def=xxx,ghi=xxx", "abc" },
+ { "abc,def=%", "abc" },
+ { "abc,def=%1", "abc" },
+ { "abc,def=%00", "abc" },
+ { "abc,def=%22", "abc" },
+ { "abc,def=\"", "abc" },
+ { "abc,def=%ed%a0%80", "abc" } };
+ for (size_t i = 0; i < std::size(aTests); ++i)
+ {
+ bool bValid = false;
+ OUString aName;
+ try
+ {
+ aName = cppu::UnoUrlDescriptor(OUString::createFromAscii(
+ aTests[i].pInput)).getName();
+ bValid = true;
+ }
+ catch (rtl::MalformedUriException &)
+ {}
+
+ CPPUNIT_ASSERT_MESSAGE("Failed to parse URI", bValid);
+ CPPUNIT_ASSERT_MESSAGE("Failed to parse URI correctly",
+ aName.equalsAscii(aTests[i].pName));
+ }
+ }
+
+ void testDescriptorKey()
+ {
+ struct Test
+ {
+ char const * pInput;
+ char const * pKey;
+ bool bPresent;
+ };
+ static Test const aTests[]
+ = { { "abc", "abc", false },
+ { "abc", "def", false },
+ { "1abc", "def", false },
+ { "123", "def", false },
+ { "abc,def=", "abc", false },
+ { "abc,def=", "def", true },
+ { "abc,def=", "defg", false },
+ { "abc,def=", "de", false },
+ { "abc,def=", "ghi", false },
+ { "abc,Def=", "def", true },
+ { "abc,Def=", "Def", true },
+ { "abc,Def=", "dEF", true },
+ { "abc,Def=", "DEF", true },
+ { "abc,def=xxx,ghi=xxx", "abc", false },
+ { "abc,def=xxx,ghi=xxx", "def", true },
+ { "abc,def=xxx,ghi=xxx", "ghi", true },
+ { "abc,def=xxx,ghi=xxx", "jkl", false } };
+ for (size_t i = 0; i < std::size(aTests); ++i)
+ {
+ bool bValid = false;
+ bool bPresent = false;
+ try
+ {
+ bPresent = cppu::UnoUrlDescriptor(OUString::createFromAscii(
+ aTests[i].pInput)).
+ hasParameter(OUString::createFromAscii(aTests[i].pKey));
+ bValid = true;
+ }
+ catch (rtl::MalformedUriException &)
+ {}
+
+ CPPUNIT_ASSERT_MESSAGE("Failed to parse URI", bValid);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Failed to detect parameter correctly",
+ aTests[i].bPresent, bPresent);
+ }
+ }
+
+ void testDescriptorValue()
+ {
+ struct Test
+ {
+ char const * pInput;
+ char const * pKey;
+ char const * pValue;
+ };
+ static Test const aTests[]
+ = { { "abc", "abc", "" },
+ { "abc", "def", "" },
+ { "1abc", "def", "" },
+ { "123", "def", "" },
+ { "abc,def=", "abc", "" },
+ { "abc,def=", "def", "" },
+ { "abc,def=", "defg", "" },
+ { "abc,def=", "de", "" },
+ { "abc,def=", "ghi", "" },
+ { "abc,Def=", "def", "" },
+ { "abc,Def=", "Def", "" },
+ { "abc,Def=", "dEF", "" },
+ { "abc,Def=", "DEF", "" },
+ { "abc,def=xxx,ghi=xxx", "abc", "" },
+ { "abc,def=xxx,ghi=xxx", "def", "xxx" },
+ { "abc,def=xxx,ghi=xxx", "ghi", "xxx" },
+ { "abc,def=xxx,ghi=xxx", "jkl", "" },
+ { "abc,def=%", "def", "%" },
+ { "abc,def=%1", "def", "%1" },
+ { "abc,def=%22", "def", "\"" },
+ { "abc,def=\"", "def", "\"" },
+ { "abc,def=abc", "def", "abc" },
+ { "abc,def=Abc", "def", "Abc" },
+ { "abc,def=aBC", "def", "aBC" },
+ { "abc,def=ABC", "def", "ABC" },
+ { "abc,def=%,ghi=", "def", "%" },
+ { "abc,def=%1,ghi=", "def", "%1" },
+ { "abc,def=%22,ghi=", "def", "\"" },
+ { "abc,def=\",ghi=", "def", "\"" },
+ { "abc,def=abc,ghi=", "def", "abc" },
+ { "abc,def=Abc,ghi=", "def", "Abc" },
+ { "abc,def=aBC,ghi=", "def", "aBC" },
+ { "abc,def=ABC,ghi=", "def", "ABC" },
+ { "abc,abc=,def=%", "def", "%" },
+ { "abc,abc=,def=%1", "def", "%1" },
+ { "abc,abc=,def=%22", "def", "\"" },
+ { "abc,abc=,def=\"", "def", "\"" },
+ { "abc,abc=,def=abc", "def", "abc" },
+ { "abc,abc=,def=Abc", "def", "Abc" },
+ { "abc,abc=,def=aBC", "def", "aBC" },
+ { "abc,abc=,def=ABC", "def", "ABC" } };
+ for (size_t i = 0; i < std::size(aTests); ++i)
+ {
+ bool bValid = false;
+ OUString aValue;
+ try
+ {
+ aValue = cppu::UnoUrlDescriptor(OUString::createFromAscii(
+ aTests[i].pInput)).
+ getParameter(OUString::createFromAscii(aTests[i].pKey));
+ bValid = true;
+ }
+ catch (rtl::MalformedUriException &)
+ {}
+ CPPUNIT_ASSERT_MESSAGE("Failed to parse URI", bValid);
+ CPPUNIT_ASSERT_MESSAGE("Failed to get param correctly",
+ aValue.equalsAscii(aTests[i].pValue));
+ }
+ }
+
+ void testUrlParsing()
+ {
+ struct Test
+ {
+ char const * pInput;
+ bool bValid;
+ };
+ static Test const aTests[]
+ = { { "", false },
+ { "abc", false },
+ { "uno", false },
+ { "uno:", false },
+ { "uno:abc;def;ghi", true },
+ { "Uno:abc;def;ghi", true },
+ { "uNO:abc;def;ghi", true },
+ { "UNO:abc;def;ghi", true },
+ { "uno:abc,def=xxx,ghi=xxx;def,ghi=xxx,jkl=xxx;ghi", true },
+ { "uno:abc,def=xxx,ghi=xxx;def,ghi=xxx,jkl=xxx,;ghi", false },
+ { "uno:abc;def;", false },
+ { "uno:abc;def;a", true },
+ { "uno:abc;def;A", true },
+ { "uno:abc;def;1", true },
+ { "uno:abc;def;$&+,/:=?@", true },
+ { "uno:abc;def;%24&+,/:=?@", false } };
+ for (size_t i = 0; i < std::size(aTests); ++i)
+ {
+ bool bValid = false;
+ try
+ {
+ cppu::UnoUrl aUrl(OUString::createFromAscii(aTests[i].pInput));
+ (void)aUrl;
+ bValid = true;
+ }
+ catch (rtl::MalformedUriException &)
+ {}
+
+ if (aTests[i].bValid)
+ {
+ CPPUNIT_ASSERT_MESSAGE("Valid uri parsed as invalid", bValid);
+ }
+ else
+ {
+ CPPUNIT_ASSERT_MESSAGE("Invalid uri parsed as valid", !bValid);
+ }
+
+ }
+ }
+
+ void testUrlConnection()
+ {
+ struct Test
+ {
+ char const * pInput;
+ char const * pConnection;
+ };
+ static Test const aTests[]
+ = { { "uno:abc;def;ghi", "abc" },
+ { "uno:Abc;def;ghi", "Abc" },
+ { "uno:aBC;def;ghi", "aBC" },
+ { "uno:ABC;def;ghi", "ABC" },
+ { "uno:abc,def=xxx,ghi=xxx;def,ghi=xxx,jkl=xxx;ghi",
+ "abc,def=xxx,ghi=xxx" } };
+ for (size_t i = 0; i < std::size(aTests); ++i)
+ {
+ bool bValid = false;
+ OUString aConnection;
+ try
+ {
+ aConnection = cppu::UnoUrl(OUString::createFromAscii(
+ aTests[i].pInput)).
+ getConnection().getDescriptor();
+ bValid = true;
+ }
+ catch (rtl::MalformedUriException &)
+ {}
+ CPPUNIT_ASSERT_MESSAGE("Failed to parse URI", bValid);
+ CPPUNIT_ASSERT_MESSAGE("Failed to get param correctly",
+ aConnection.equalsAscii(
+ aTests[i].pConnection));
+ }
+ }
+
+ void testUrlProtocol()
+ {
+ struct Test
+ {
+ char const * pInput;
+ char const * pProtocol;
+ };
+ static Test const aTests[]
+ = { { "uno:abc;def;ghi", "def" },
+ { "uno:abc;Def;ghi", "Def" },
+ { "uno:abc;dEF;ghi", "dEF" },
+ { "uno:abc;DEF;ghi", "DEF" },
+ { "uno:abc,def=xxx,ghi=xxx;def,ghi=xxx,jkl=xxx;ghi",
+ "def,ghi=xxx,jkl=xxx" } };
+ for (size_t i = 0; i < std::size(aTests); ++i)
+ {
+ bool bValid = false;
+ OUString aProtocol;
+ try
+ {
+ aProtocol = cppu::UnoUrl(OUString::createFromAscii(
+ aTests[i].pInput)).
+ getProtocol().getDescriptor();
+ bValid = true;
+ }
+ catch (rtl::MalformedUriException &)
+ {}
+ CPPUNIT_ASSERT_MESSAGE("Failed to parse URI", bValid);
+ CPPUNIT_ASSERT_MESSAGE("Failed to get protocol correctly",
+ aProtocol.equalsAscii(
+ aTests[i].pProtocol));
+ }
+ }
+
+ void testUrlObjectName()
+ {
+ struct Test
+ {
+ char const * pInput;
+ char const * pObjectName;
+ };
+ static Test const aTests[]
+ = { { "uno:abc;def;ghi", "ghi" },
+ { "uno:abc;def;Ghi", "Ghi" },
+ { "uno:abc;def;gHI", "gHI" },
+ { "uno:abc;def;GHI", "GHI" },
+ { "uno:abc,def=xxx,ghi=xxx;def,ghi=xxx,jkl=xxx;ghi", "ghi" },
+ { "uno:abc;def;a", "a" },
+ { "uno:abc;def;A", "A" },
+ { "uno:abc;def;1", "1" },
+ { "uno:abc;def;$&+,/:=?@", "$&+,/:=?@" } };
+ for (size_t i = 0; i < std::size(aTests); ++i)
+ {
+ bool bValid = false;
+ OUString aObjectName;
+ try
+ {
+ aObjectName = cppu::UnoUrl(OUString::createFromAscii(
+ aTests[i].pInput)).getObjectName();
+ bValid = true;
+ }
+ catch (rtl::MalformedUriException &)
+ {}
+ CPPUNIT_ASSERT_MESSAGE("Failed to parse URI", bValid);
+ CPPUNIT_ASSERT_MESSAGE("Failed to get protocol correctly",
+ aObjectName.equalsAscii(
+ aTests[i].pObjectName));
+ }
+ }
+
+ // Automatic registration code
+ CPPUNIT_TEST_SUITE(UrlTest);
+ CPPUNIT_TEST(testDescriptorParsing);
+ CPPUNIT_TEST(testDescriptorDescriptor);
+ CPPUNIT_TEST(testDescriptorName);
+ CPPUNIT_TEST(testDescriptorKey);
+ CPPUNIT_TEST(testDescriptorValue);
+ CPPUNIT_TEST(testUrlParsing);
+ CPPUNIT_TEST(testUrlConnection);
+ CPPUNIT_TEST(testUrlProtocol);
+ CPPUNIT_TEST(testUrlObjectName);
+ CPPUNIT_TEST_SUITE_END();
+ };
+} // namespace cppu_ifcontainer
+
+CPPUNIT_TEST_SUITE_REGISTRATION(cppu_unourl::UrlTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/qa/weak/test_weak.cxx b/cppuhelper/qa/weak/test_weak.cxx
new file mode 100644
index 000000000..4db360b40
--- /dev/null
+++ b/cppuhelper/qa/weak/test_weak.cxx
@@ -0,0 +1,99 @@
+/* -*- 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/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/XAdapter.hpp>
+#include <com/sun/star/uno/XReference.hpp>
+#include <com/sun/star/uno/XWeak.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/weak.hxx>
+#include <rtl/ref.hxx>
+#include <sal/types.h>
+
+namespace {
+
+class Reference: public cppu::WeakImplHelper< css::uno::XReference > {
+public:
+ Reference(): m_disposed(false) {}
+
+ void SAL_CALL dispose() override {
+ m_disposed = true;
+ handleDispose();
+ }
+
+ bool isDisposed() const { return m_disposed; }
+
+protected:
+ virtual void handleDispose() {};
+
+private:
+ bool m_disposed;
+};
+
+class RuntimeExceptionReference: public Reference {
+protected:
+ void handleDispose() override {
+ throw css::uno::RuntimeException();
+ }
+};
+
+class DisposedExceptionReference: public Reference {
+protected:
+ void handleDispose() override {
+ throw css::lang::DisposedException();
+ }
+};
+
+class Test: public ::CppUnit::TestFixture {
+public:
+ void testReferenceDispose();
+
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testReferenceDispose);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void Test::testReferenceDispose() {
+ css::uno::Reference< css::uno::XWeak > w(new ::cppu::OWeakObject);
+ css::uno::Reference< css::uno::XAdapter > a(w->queryAdapter());
+ ::rtl::Reference< Reference > r1(new RuntimeExceptionReference);
+ ::rtl::Reference< Reference > r2(new Reference);
+ ::rtl::Reference< Reference > r3(new DisposedExceptionReference);
+ a->addReference(r1);
+ a->addReference(r2);
+ a->addReference(r3);
+ w.clear();
+ CPPUNIT_ASSERT(r1->isDisposed());
+ CPPUNIT_ASSERT(r2->isDisposed());
+ CPPUNIT_ASSERT(r3->isDisposed());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/access_control.cxx b/cppuhelper/source/access_control.cxx
new file mode 100644
index 000000000..0e18ef786
--- /dev/null
+++ b/cppuhelper/source/access_control.cxx
@@ -0,0 +1,131 @@
+/* -*- 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 <cppuhelper/access_control.hxx>
+
+#include <com/sun/star/security/XAccessController.hpp>
+#include <com/sun/star/security/RuntimePermission.hpp>
+#include <com/sun/star/io/FilePermission.hpp>
+#include <com/sun/star/connection/SocketPermission.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+using namespace ::osl;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace
+{
+ OUString str_ac_singleton()
+ {
+ return "/singletons/com.sun.star.security.theAccessController";
+ }
+}
+
+namespace cppu
+{
+
+AccessControl::AccessControl( Reference< XComponentContext > const & xContext )
+{
+ if (! (xContext->getValueByName( str_ac_singleton() ) >>= m_xController))
+ {
+ throw SecurityException( "no access controller!" );
+ }
+}
+
+AccessControl::AccessControl(
+ Reference< security::XAccessController > const & xController )
+ : m_xController( xController )
+{
+ if (! m_xController.is())
+ {
+ throw SecurityException( "no access controller!" );
+ }
+}
+
+AccessControl::AccessControl( AccessControl const & ac )
+ : m_xController( ac.m_xController )
+{
+ if (! m_xController.is())
+ {
+ throw SecurityException( "no access controller!" );
+ }
+}
+
+namespace {
+
+#ifdef _WIN32
+#pragma pack(push, 8)
+#endif
+ // binary comp. to all Permission structs
+ struct permission
+ {
+ rtl_uString * m_str1;
+ rtl_uString * m_str2;
+ };
+#ifdef _WIN32
+#pragma pack(pop)
+#endif
+
+void checkPermission(
+ Reference< security::XAccessController > const & xController,
+ Type const & type, rtl_uString * str1, rtl_uString * str2 )
+{
+ permission perm;
+ perm.m_str1 = str1;
+ perm.m_str2 = str2;
+
+ uno_Any a;
+ a.pType = type.getTypeLibType();
+ a.pData = &perm;
+
+ xController->checkPermission( * static_cast< Any * >( &a ) );
+}
+
+}
+
+void AccessControl::checkRuntimePermission(
+ OUString const & name )
+{
+ checkPermission(
+ m_xController,
+ cppu::UnoType<security::RuntimePermission>::get(), name.pData, nullptr );
+}
+
+void AccessControl::checkFilePermission(
+ OUString const & url,
+ OUString const & actions )
+{
+ checkPermission(
+ m_xController,
+ cppu::UnoType<io::FilePermission>::get(), url.pData, actions.pData );
+}
+
+void AccessControl::checkSocketPermission(
+ OUString const & host,
+ OUString const & actions )
+{
+ checkPermission(
+ m_xController,
+ cppu::UnoType<connection::SocketPermission>::get(), host.pData, actions.pData );
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/bootstrap.cxx b/cppuhelper/source/bootstrap.cxx
new file mode 100644
index 000000000..f468518ba
--- /dev/null
+++ b/cppuhelper/source/bootstrap.cxx
@@ -0,0 +1,242 @@
+/* -*- 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 <chrono>
+#include <cstring>
+
+#include <rtl/bootstrap.hxx>
+#include <rtl/random.h>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/uri.hxx>
+#include <osl/file.hxx>
+#include <osl/security.hxx>
+#include <osl/thread.hxx>
+#include <o3tl/char16_t2wchar_t.hxx>
+#include <osl/process.h>
+
+#include <cppuhelper/bootstrap.hxx>
+#include <cppuhelper/findsofficepath.h>
+
+#include <com/sun/star/bridge/UnoUrlResolver.hpp>
+#include <com/sun/star/bridge/XUnoUrlResolver.hpp>
+
+#include "macro_expander.hxx"
+
+namespace com :: sun :: star :: uno { class XComponentContext; }
+
+using namespace ::osl;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+using rtl::Bootstrap;
+
+namespace cppu
+{
+
+BootstrapException::BootstrapException()
+{
+}
+
+BootstrapException::BootstrapException( const OUString & rMessage )
+ :m_aMessage( rMessage )
+{
+}
+
+BootstrapException::BootstrapException( const BootstrapException & e )
+{
+ m_aMessage = e.m_aMessage;
+}
+
+BootstrapException::~BootstrapException()
+{
+}
+
+BootstrapException & BootstrapException::operator=( const BootstrapException & e )
+{
+ m_aMessage = e.m_aMessage;
+ return *this;
+}
+
+const OUString & BootstrapException::getMessage() const
+{
+ return m_aMessage;
+}
+
+Reference< XComponentContext > SAL_CALL bootstrap()
+{
+ Reference< XComponentContext > xRemoteContext;
+
+ try
+ {
+ auto* p1 = cppuhelper_detail_findSofficePath();
+ if (p1 == nullptr) {
+ throw BootstrapException(
+ "no soffice installation found!");
+ }
+ OUString p2;
+#if defined(_WIN32)
+ p2 = o3tl::toU(p1);
+ free(p1);
+#else
+ bool bOk = rtl_convertStringToUString(
+ &p2.pData, p1, std::strlen(p1), osl_getThreadTextEncoding(),
+ (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
+ RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
+ RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR));
+ free(p1);
+ if (!bOk)
+ {
+ throw BootstrapException(
+ "bad characters in soffice installation path!");
+ }
+#endif
+ OUString path;
+ if (osl::FileBase::getFileURLFromSystemPath(p2, path) !=
+ osl::FileBase::E_None)
+ {
+ throw BootstrapException(
+ "cannot convert soffice installation path to URL!");
+ }
+ if (!path.isEmpty() && !path.endsWith("/")) {
+ path += "/";
+ }
+
+ OUString uri;
+ if (!Bootstrap::get("URE_BOOTSTRAP", uri)) {
+ Bootstrap::set(
+ "URE_BOOTSTRAP",
+ Bootstrap::encode(
+ path +
+#if defined MACOSX
+ "../Resources/"
+#endif
+ SAL_CONFIGFILE("fundamental")));
+ }
+
+ // create default local component context
+ Reference< XComponentContext > xLocalContext(
+ defaultBootstrap_InitialComponentContext() );
+ if ( !xLocalContext.is() )
+ throw BootstrapException( "no local component context!" );
+
+ // create a random pipe name
+ rtlRandomPool hPool = rtl_random_createPool();
+ if ( hPool == nullptr )
+ throw BootstrapException( "cannot create random pool!" );
+ sal_uInt8 bytes[ 16 ];
+ if ( rtl_random_getBytes( hPool, bytes, std::size( bytes ) )
+ != rtl_Random_E_None )
+ throw BootstrapException( "random pool error!" );
+ rtl_random_destroyPool( hPool );
+ OUStringBuffer buf("uno");
+ for (unsigned char byte : bytes)
+ buf.append( static_cast< sal_Int32 >( byte ) );
+ OUString sPipeName( buf.makeStringAndClear() );
+
+ // arguments
+ OUString args [] = {
+ OUString("--nologo"),
+ OUString("--nodefault"),
+ OUString("--norestore"),
+ OUString("--nolockcheck"),
+ OUString("--accept=pipe,name=" + sPipeName + ";urp;")
+ };
+ rtl_uString * ar_args [] = {
+ args[ 0 ].pData,
+ args[ 1 ].pData,
+ args[ 2 ].pData,
+ args[ 3 ].pData,
+ args[ 4 ].pData
+ };
+ ::osl::Security sec;
+
+ // start office process
+ oslProcess hProcess = nullptr;
+ oslProcessError rc = osl_executeProcess(
+ OUString(path + "soffice").pData, ar_args, std::size( ar_args ),
+ osl_Process_DETACHED,
+ sec.getHandle(),
+ nullptr, // => current working dir
+ nullptr, 0, // => no env vars
+ &hProcess );
+ switch ( rc )
+ {
+ case osl_Process_E_None:
+ osl_freeProcessHandle( hProcess );
+ break;
+ case osl_Process_E_NotFound:
+ throw BootstrapException( "image not found!" );
+ case osl_Process_E_TimedOut:
+ throw BootstrapException( "timeout occurred!" );
+ case osl_Process_E_NoPermission:
+ throw BootstrapException( "permission denied!" );
+ case osl_Process_E_Unknown:
+ throw BootstrapException( "unknown error!" );
+ case osl_Process_E_InvalidError:
+ default:
+ throw BootstrapException( "unmapped error!" );
+ }
+
+ // create a URL resolver
+ Reference< bridge::XUnoUrlResolver > xUrlResolver(
+ bridge::UnoUrlResolver::create( xLocalContext ) );
+
+ // connection string
+ OUString sConnectString( "uno:pipe,name=" + sPipeName + ";urp;StarOffice.ComponentContext" );
+
+ // wait until office is started
+ for ( ; ; )
+ {
+ try
+ {
+ // try to connect to office
+ xRemoteContext.set(
+ xUrlResolver->resolve( sConnectString ), UNO_QUERY_THROW );
+ break;
+ }
+ catch ( connection::NoConnectException & )
+ {
+ // wait 500 ms, then try to connect again
+ ::osl::Thread::wait( std::chrono::milliseconds(500) );
+ }
+ }
+ }
+ catch ( Exception & e )
+ {
+ throw BootstrapException(
+ "unexpected UNO exception caught: " + e.Message );
+ }
+
+ return xRemoteContext;
+}
+
+OUString bootstrap_expandUri(OUString const & uri) {
+ OUString rest;
+ return uri.startsWith("vnd.sun.star.expand:", &rest)
+ ? cppuhelper::detail::expandMacros(
+ rtl::Uri::decode(
+ rest, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8))
+ : uri;
+}
+
+} // namespace cppu
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/compat.cxx b/cppuhelper/source/compat.cxx
new file mode 100644
index 000000000..f6572ea47
--- /dev/null
+++ b/cppuhelper/source/compat.cxx
@@ -0,0 +1,172 @@
+/* -*- 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 <cstdlib>
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <osl/module.h>
+#include <sal/types.h>
+
+namespace com::sun::star {
+ namespace lang {
+ class XMultiComponentFactory;
+ class XMultiServiceFactory;
+ class XTypeProvider;
+ }
+ namespace reflection { class XIdlClass; }
+ namespace registry {
+ class XRegistryKey;
+ class XSimpleRegistry;
+ }
+ namespace uno {
+ class XComponentContext;
+ class XInterface;
+ }
+}
+
+// Stubs for removed functionality, to be killed when we bump cppuhelper SONAME
+
+namespace cppu {
+
+SAL_DLLPUBLIC_EXPORT
+css::uno::Reference< css::lang::XMultiComponentFactory > bootstrapInitialSF(
+ OUString const &)
+{
+ for (;;) { std::abort(); } // avoid "must return a value" warnings
+}
+
+SAL_DLLPUBLIC_EXPORT css::uno::Reference< css::uno::XComponentContext > SAL_CALL
+bootstrap_InitialComponentContext(
+ css::uno::Reference< css::registry::XSimpleRegistry > const &,
+ OUString const &)
+{
+ for (;;) { std::abort(); } // avoid "must return a value" warnings
+}
+
+SAL_DLLPUBLIC_EXPORT css::uno::Reference< css::registry::XSimpleRegistry >
+SAL_CALL createNestedRegistry(OUString const &) {
+ for (;;) { std::abort(); } // avoid "must return a value" warnings
+}
+
+SAL_DLLPUBLIC_EXPORT css::uno::Reference< css::lang::XMultiServiceFactory >
+SAL_CALL createRegistryServiceFactory(
+ OUString const &, OUString const &, sal_Bool,
+ OUString const &)
+{
+ for (;;) { std::abort(); } // avoid "must return a value" warnings
+}
+
+SAL_DLLPUBLIC_EXPORT css::uno::Reference< css::registry::XSimpleRegistry >
+SAL_CALL createSimpleRegistry(OUString const &) {
+ for (;;) { std::abort(); } // avoid "must return a value" warnings
+}
+
+SAL_DLLPUBLIC_EXPORT css::reflection::XIdlClass * SAL_CALL
+createStandardClassWithSequence(
+ css::uno::Reference< css::lang::XMultiServiceFactory > const &,
+ OUString const &,
+ css::uno::Reference< css::reflection::XIdlClass > const &,
+ css::uno::Sequence< OUString > const &)
+{
+ for (;;) { std::abort(); } // avoid "must return a value" warnings
+}
+
+SAL_DLLPUBLIC_EXPORT css::uno::Reference<css::uno::XInterface> SAL_CALL
+invokeStaticComponentFactory(
+ oslGenericFunction, OUString const &,
+ css::uno::Reference<css::lang::XMultiServiceFactory> const &,
+ css::uno::Reference<css::registry::XRegistryKey> const &,
+ OUString const &)
+{
+ for (;;) { std::abort(); } // avoid "must return a value" warnings
+}
+
+SAL_DLLPUBLIC_EXPORT css::uno::Reference<css::uno::XInterface> SAL_CALL
+loadSharedLibComponentFactory(
+ OUString const &, OUString const &, OUString const &,
+ css::uno::Reference<css::lang::XMultiServiceFactory> const &,
+ css::uno::Reference<css::registry::XRegistryKey> const &,
+ OUString const &)
+{
+ for (;;) { std::abort(); } // avoid "must return a value" warnings
+}
+
+struct SAL_DLLPUBLIC_EXPORT ClassData {
+ css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId();
+
+ css::uno::Sequence<css::uno::Type> SAL_CALL getTypes();
+
+ void SAL_CALL initTypeProvider();
+
+ css::uno::Any SAL_CALL query(
+ css::uno::Type const &, css::lang::XTypeProvider *);
+
+ void SAL_CALL writeTypeOffset(css::uno::Type const &, sal_Int32);
+};
+
+css::uno::Sequence<sal_Int8> ClassData::getImplementationId() {
+ for (;;) { std::abort(); } // avoid "must return a value" warnings
+}
+
+css::uno::Sequence<css::uno::Type> ClassData::getTypes() {
+ for (;;) { std::abort(); } // avoid "must return a value" warnings
+}
+
+void ClassData::initTypeProvider() {
+ std::abort();
+}
+
+css::uno::Any ClassData::query(
+ css::uno::Type const &, css::lang::XTypeProvider *)
+{
+ for (;;) { std::abort(); } // avoid "must return a value" warnings
+}
+
+void ClassData::writeTypeOffset(css::uno::Type const &, sal_Int32) {
+ std::abort();
+}
+
+SAL_WNOUNREACHABLE_CODE_PUSH
+struct SAL_DLLPUBLIC_EXPORT ClassDataBase {
+ ClassDataBase();
+
+ explicit ClassDataBase(sal_Int32);
+
+ ~ClassDataBase();
+};
+
+ClassDataBase::ClassDataBase() {
+ std::abort();
+}
+
+ClassDataBase::ClassDataBase(sal_Int32) {
+ std::abort();
+}
+
+ClassDataBase::~ClassDataBase() {
+ std::abort();
+}
+SAL_WNOUNREACHABLE_CODE_POP
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/component.cxx b/cppuhelper/source/component.cxx
new file mode 100644
index 000000000..369e2ead7
--- /dev/null
+++ b/cppuhelper/source/component.cxx
@@ -0,0 +1,223 @@
+/* -*- 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 <sal/log.hxx>
+#include <cppuhelper/component.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+
+using namespace osl;
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+
+namespace cppu
+{
+
+
+// class OComponentHelper
+
+
+OComponentHelper::OComponentHelper( Mutex & rMutex )
+ : rBHelper( rMutex )
+{
+}
+OComponentHelper::~OComponentHelper()
+{
+}
+
+Any OComponentHelper::queryInterface( Type const & rType )
+{
+ return OWeakAggObject::queryInterface( rType );
+}
+Any OComponentHelper::queryAggregation( Type const & rType )
+{
+ if (rType == cppu::UnoType<lang::XComponent>::get())
+ {
+ void * p = static_cast< lang::XComponent * >( this );
+ return Any( &p, rType );
+ }
+ if (rType == cppu::UnoType<lang::XTypeProvider>::get())
+ {
+ void * p = static_cast< lang::XTypeProvider * >( this );
+ return Any( &p, rType );
+ }
+ return OWeakAggObject::queryAggregation( rType );
+}
+void OComponentHelper::acquire() noexcept
+{
+ OWeakAggObject::acquire();
+}
+
+void OComponentHelper::release() noexcept
+{
+ Reference<XInterface > x( xDelegator );
+ if (! x.is())
+ {
+ if (osl_atomic_decrement( &m_refCount ) == 0)
+ {
+ if (! rBHelper.bDisposed)
+ {
+ // *before* again incrementing our ref count, ensure that our weak connection point
+ // will not create references to us anymore (via XAdapter::queryAdapted)
+ disposeWeakConnectionPoint();
+
+ Reference<XInterface > xHoldAlive( *this );
+ // First dispose
+ try
+ {
+ dispose();
+ }
+ catch (css::uno::RuntimeException & exc)
+ {
+ // release should not throw exceptions
+ SAL_WARN( "cppuhelper", exc );
+ }
+
+ // only the alive ref holds the object
+ OSL_ASSERT( m_refCount == 1 );
+ // destroy the object if xHoldAlive decrement the refcount to 0
+ return;
+ }
+ }
+ // restore the reference count
+ osl_atomic_increment( &m_refCount );
+ }
+ OWeakAggObject::release();
+}
+
+Sequence< Type > OComponentHelper::getTypes()
+{
+ static OTypeCollection s_aTypes(
+ cppu::UnoType<lang::XComponent>::get(),
+ cppu::UnoType<lang::XTypeProvider>::get(),
+ cppu::UnoType<XAggregation>::get(),
+ cppu::UnoType<XWeak>::get() );
+
+ return s_aTypes.getTypes();
+}
+
+// XComponent
+void OComponentHelper::disposing()
+{
+}
+
+// XComponent
+void OComponentHelper::dispose()
+{
+ // An frequently programming error is to release the last
+ // reference to this object in the disposing message.
+ // Make it robust, hold a self Reference.
+ Reference<XComponent > xSelf( this );
+
+ // Guard dispose against multiple threading
+ // Remark: It is an error to call dispose more than once
+ bool bDoDispose = false;
+ {
+ MutexGuard aGuard( rBHelper.rMutex );
+ if( !rBHelper.bDisposed && !rBHelper.bInDispose )
+ {
+ // only one call go into this section
+ rBHelper.bInDispose = true;
+ bDoDispose = true;
+ }
+ }
+
+ // Do not hold the mutex because we are broadcasting
+ if( bDoDispose )
+ {
+ // Create an event with this as sender
+ try
+ {
+ try
+ {
+ Reference<XInterface > xSource(
+ Reference<XInterface >::query( static_cast<XComponent *>(this) ) );
+ EventObject aEvt;
+ aEvt.Source = xSource;
+ // inform all listeners to release this object
+ // The listener container are automatically cleared
+ rBHelper.aLC.disposeAndClear( aEvt );
+ // notify subclasses to do their dispose
+ disposing();
+ }
+ catch (...)
+ {
+ MutexGuard aGuard( rBHelper.rMutex );
+ // bDispose and bInDisposing must be set in this order:
+ rBHelper.bDisposed = true;
+ rBHelper.bInDispose = false;
+ throw;
+ }
+ MutexGuard aGuard( rBHelper.rMutex );
+ // bDispose and bInDisposing must be set in this order:
+ rBHelper.bDisposed = true;
+ rBHelper.bInDispose = false;
+ }
+ catch (RuntimeException &)
+ {
+ throw;
+ }
+ catch (Exception & exc)
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw lang::WrappedTargetRuntimeException(
+ "unexpected UNO exception caught: " + exc.Message,
+ nullptr, anyEx );
+ }
+ }
+ else
+ {
+ // in a multithreaded environment, it can't be avoided
+ // that dispose is called twice.
+ // However this condition is traced, because it MAY indicate an error.
+ SAL_WARN("cppuhelper", "OComponentHelper::dispose() - dispose called twice" );
+ }
+}
+
+// XComponent
+void OComponentHelper::addEventListener(
+ const Reference<XEventListener > & rxListener )
+{
+ ClearableMutexGuard aGuard( rBHelper.rMutex );
+ if (rBHelper.bDisposed || rBHelper.bInDispose)
+ {
+ aGuard.clear();
+ Reference< XInterface > x( static_cast<XComponent *>(this), UNO_QUERY );
+ rxListener->disposing( EventObject( x ) );
+ }
+ else
+ {
+ rBHelper.addListener( cppu::UnoType<decltype(rxListener)>::get(), rxListener );
+ }
+}
+
+// XComponent
+void OComponentHelper::removeEventListener(
+ const Reference<XEventListener > & rxListener )
+{
+ rBHelper.removeListener( cppu::UnoType<decltype(rxListener)>::get(), rxListener );
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/component_context.cxx b/cppuhelper/source/component_context.cxx
new file mode 100644
index 000000000..81c7d306f
--- /dev/null
+++ b/cppuhelper/source/component_context.cxx
@@ -0,0 +1,590 @@
+/* -*- 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 <unordered_map>
+
+#include <osl/diagnose.h>
+#include <osl/mutex.hxx>
+
+#include <sal/log.hxx>
+
+#include <uno/lbnames.h>
+#include <uno/mapping.hxx>
+
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/component_context.hxx>
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/lang/XSingleComponentFactory.hpp>
+#include <com/sun/star/lang/XMultiComponentFactory.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/uno/DeploymentException.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+
+#include <comphelper/sequence.hxx>
+
+#include <memory>
+#include <utility>
+
+constexpr OUStringLiteral SMGR_SINGLETON = u"/singletons/com.sun.star.lang.theServiceManager";
+constexpr OUStringLiteral TDMGR_SINGLETON = u"/singletons/com.sun.star.reflection.theTypeDescriptionManager";
+constexpr OUStringLiteral AC_SINGLETON = u"/singletons/com.sun.star.security.theAccessController";
+
+using namespace ::osl;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+
+namespace cppu
+{
+
+static void try_dispose( Reference< XInterface > const & xInstance )
+{
+ Reference< lang::XComponent > xComp( xInstance, UNO_QUERY );
+ if (xComp.is())
+ {
+ xComp->dispose();
+ }
+}
+
+static void try_dispose( Reference< lang::XComponent > const & xComp )
+{
+ if (xComp.is())
+ {
+ xComp->dispose();
+ }
+}
+
+namespace {
+
+class DisposingForwarder
+ : public WeakImplHelper< lang::XEventListener >
+{
+ Reference< lang::XComponent > m_xTarget;
+
+ explicit DisposingForwarder( Reference< lang::XComponent > const & xTarget )
+ : m_xTarget( xTarget )
+ {
+ OSL_ASSERT( m_xTarget.is() );
+ }
+public:
+ // listens at source for disposing, then disposes target
+ static inline void listen(
+ Reference< lang::XComponent > const & xSource,
+ Reference< lang::XComponent > const & xTarget );
+
+ virtual void SAL_CALL disposing( lang::EventObject const & rSource ) override;
+};
+
+}
+
+inline void DisposingForwarder::listen(
+ Reference< lang::XComponent > const & xSource,
+ Reference< lang::XComponent > const & xTarget )
+{
+ if (xSource.is())
+ {
+ xSource->addEventListener( new DisposingForwarder( xTarget ) );
+ }
+}
+
+void DisposingForwarder::disposing( lang::EventObject const & )
+{
+ m_xTarget->dispose();
+ m_xTarget.clear();
+}
+
+namespace {
+
+class ComponentContext
+ : private cppu::BaseMutex
+ , public WeakComponentImplHelper< XComponentContext,
+ container::XNameContainer >
+{
+protected:
+ Reference< XComponentContext > m_xDelegate;
+
+ struct ContextEntry
+ {
+ Any value;
+ bool lateInit;
+
+ ContextEntry( Any value_, bool lateInit_ )
+ : value(std::move( value_ ))
+ , lateInit( lateInit_ )
+ {}
+ };
+ typedef std::unordered_map< OUString, ContextEntry > t_map;
+ t_map m_map;
+
+ Reference< lang::XMultiComponentFactory > m_xSMgr;
+
+protected:
+ Any lookupMap( OUString const & rName );
+
+ virtual void SAL_CALL disposing() override;
+public:
+ ComponentContext(
+ ContextEntry_Init const * pEntries, sal_Int32 nEntries,
+ Reference< XComponentContext > const & xDelegate );
+
+ // XComponentContext
+ virtual Any SAL_CALL getValueByName( OUString const & rName ) override;
+ virtual Reference<lang::XMultiComponentFactory> SAL_CALL getServiceManager() override;
+
+ // XNameContainer
+ virtual void SAL_CALL insertByName(
+ OUString const & name, Any const & element ) override;
+ virtual void SAL_CALL removeByName( OUString const & name ) override;
+ // XNameReplace
+ virtual void SAL_CALL replaceByName(
+ OUString const & name, Any const & element ) override;
+ // XNameAccess
+ virtual Any SAL_CALL getByName( OUString const & name ) override;
+ virtual Sequence<OUString> SAL_CALL getElementNames() override;
+ virtual sal_Bool SAL_CALL hasByName( OUString const & name ) override;
+ // XElementAccess
+ virtual Type SAL_CALL getElementType() override;
+ virtual sal_Bool SAL_CALL hasElements() override;
+};
+
+}
+
+// XNameContainer
+
+void ComponentContext::insertByName(
+ OUString const & name, Any const & element )
+{
+ ContextEntry entry(
+ element,
+ /* lateInit_: */
+ name.startsWith( "/singletons/" ) &&
+ !element.hasValue() );
+ MutexGuard guard( m_aMutex );
+ std::pair<t_map::iterator, bool> insertion( m_map.emplace(
+ name, entry ) );
+ if (! insertion.second)
+ throw container::ElementExistException(
+ "element already exists: " + name,
+ static_cast<OWeakObject *>(this) );
+}
+
+
+void ComponentContext::removeByName( OUString const & name )
+{
+ MutexGuard guard( m_aMutex );
+ t_map::iterator iFind( m_map.find( name ) );
+ if (iFind == m_map.end())
+ throw container::NoSuchElementException(
+ "no such element: " + name,
+ static_cast<OWeakObject *>(this) );
+
+ m_map.erase(iFind);
+}
+
+// XNameReplace
+
+void ComponentContext::replaceByName(
+ OUString const & name, Any const & element )
+{
+ MutexGuard guard( m_aMutex );
+ t_map::iterator iFind( m_map.find( name ) );
+ if (iFind == m_map.end())
+ throw container::NoSuchElementException(
+ "no such element: " + name,
+ static_cast<OWeakObject *>(this) );
+ if (name.startsWith( "/singletons/" ) &&
+ !element.hasValue())
+ {
+ iFind->second.value.clear();
+ iFind->second.lateInit = true;
+ }
+ else
+ {
+ iFind->second.value = element;
+ iFind->second.lateInit = false;
+ }
+}
+
+// XNameAccess
+
+Any ComponentContext::getByName( OUString const & name )
+{
+ return getValueByName( name );
+}
+
+
+Sequence<OUString> ComponentContext::getElementNames()
+{
+ MutexGuard guard( m_aMutex );
+ return comphelper::mapKeysToSequence(m_map);
+}
+
+
+sal_Bool ComponentContext::hasByName( OUString const & name )
+{
+ MutexGuard guard( m_aMutex );
+ return m_map.find( name ) != m_map.end();
+}
+
+// XElementAccess
+
+Type ComponentContext::getElementType()
+{
+ return cppu::UnoType<void>::get();
+}
+
+
+sal_Bool ComponentContext::hasElements()
+{
+ MutexGuard guard( m_aMutex );
+ return ! m_map.empty();
+}
+
+
+Any ComponentContext::lookupMap( OUString const & rName )
+{
+ ResettableMutexGuard guard( m_aMutex );
+ t_map::iterator iFind( m_map.find( rName ) );
+ if (iFind == m_map.end())
+ return Any();
+
+ ContextEntry& rFindEntry = iFind->second;
+ if (! rFindEntry.lateInit)
+ return rFindEntry.value;
+
+ // late init singleton entry
+ Reference< XInterface > xInstance;
+ guard.clear();
+
+ try
+ {
+ Any usesService( getValueByName( rName + "/service" ) );
+ Any args_( getValueByName( rName + "/arguments" ) );
+ Sequence<Any> args;
+ if (args_.hasValue() && !(args_ >>= args))
+ {
+ args = { args_ };
+ }
+
+ Reference< lang::XSingleComponentFactory > xFac;
+ if (usesService >>= xFac) // try via factory
+ {
+ xInstance = args.hasElements()
+ ? xFac->createInstanceWithArgumentsAndContext( args, this )
+ : xFac->createInstanceWithContext( this );
+ }
+ else
+ {
+ Reference< lang::XSingleServiceFactory > xFac2;
+ if (usesService >>= xFac2)
+ {
+ // try via old XSingleServiceFactory
+ xInstance = args.hasElements()
+ ? xFac2->createInstanceWithArguments( args )
+ : xFac2->createInstance();
+ }
+ else if (m_xSMgr.is()) // optionally service name
+ {
+ OUString serviceName;
+ if ((usesService >>= serviceName) &&
+ !serviceName.isEmpty())
+ {
+ xInstance = args.hasElements()
+ ? m_xSMgr->createInstanceWithArgumentsAndContext(
+ serviceName, args, this )
+ : m_xSMgr->createInstanceWithContext(
+ serviceName, this );
+ }
+ }
+ }
+ }
+ catch (const RuntimeException &)
+ {
+ throw;
+ }
+ catch (const Exception & exc)
+ {
+ SAL_WARN(
+ "cppuhelper",
+ "exception occurred raising singleton \"" << rName << "\": "
+ << exc);
+ }
+
+ SAL_WARN_IF(!xInstance.is(),
+ "cppuhelper", "no service object raising singleton " << rName);
+
+ Any ret;
+ guard.reset();
+ iFind = m_map.find( rName );
+ if (iFind != m_map.end())
+ {
+ ContextEntry & rEntry = iFind->second;
+ if (rEntry.lateInit)
+ {
+ rEntry.value <<= xInstance;
+ rEntry.lateInit = false;
+ return rEntry.value;
+ }
+ ret = rEntry.value;
+ }
+ guard.clear();
+ if (ret != xInstance) {
+ try_dispose( xInstance );
+ }
+ return ret;
+}
+
+
+Any ComponentContext::getValueByName( OUString const & rName )
+{
+ // to determine the root context:
+ if ( rName == "_root" )
+ {
+ if (m_xDelegate.is())
+ return m_xDelegate->getValueByName( rName );
+ return Any( Reference<XComponentContext>(this) );
+ }
+
+ Any ret( lookupMap( rName ) );
+ if (!ret.hasValue() && m_xDelegate.is())
+ {
+ return m_xDelegate->getValueByName( rName );
+ }
+ return ret;
+}
+
+Reference< lang::XMultiComponentFactory > ComponentContext::getServiceManager()
+{
+ if ( !m_xSMgr.is() )
+ {
+ throw DeploymentException(
+ "null component context service manager",
+ static_cast<OWeakObject *>(this) );
+ }
+ return m_xSMgr;
+}
+
+void ComponentContext::disposing()
+{
+ Reference< lang::XComponent > xTDMgr, xAC; // to be disposed separately
+
+ // dispose all context objects
+ for ( auto& [rName, rEntry] : m_map )
+ {
+ // service manager disposed separately
+ if (!m_xSMgr.is() ||
+ !rName.startsWith( SMGR_SINGLETON ))
+ {
+ if (rEntry.lateInit)
+ {
+ // late init
+ MutexGuard guard( m_aMutex );
+ if (rEntry.lateInit)
+ {
+ rEntry.value.clear(); // release factory
+ rEntry.lateInit = false;
+ continue;
+ }
+ }
+
+ Reference< lang::XComponent > xComp;
+ rEntry.value >>= xComp;
+ if (xComp.is())
+ {
+ if ( rName == TDMGR_SINGLETON )
+ {
+ xTDMgr = xComp;
+ }
+ else if ( rName == AC_SINGLETON )
+ {
+ xAC = xComp;
+ }
+ else // dispose immediately
+ {
+ xComp->dispose();
+ }
+ }
+ }
+ }
+
+ // dispose service manager
+ try_dispose( m_xSMgr );
+ m_xSMgr.clear();
+ // dispose ac
+ try_dispose( xAC );
+ // dispose tdmgr; revokes callback from cppu runtime
+ try_dispose( xTDMgr );
+
+ m_map.clear();
+
+ // Hack to terminate any JNI bridge's AsynchronousFinalizer thread (as JNI
+ // proxies get finalized with arbitrary delay, so the bridge typically does
+ // not dispose itself early enough before the process exits):
+ uno_Environment ** envs;
+ sal_Int32 envCount;
+ uno_getRegisteredEnvironments(
+ &envs, &envCount, &rtl_allocateMemory, OUString("java").pData);
+ assert(envCount >= 0);
+ assert(envCount == 0 || envs != nullptr);
+ if (envs) {
+ for (sal_Int32 i = 0; i != envCount; ++i) {
+ assert(envs[i] != nullptr);
+ assert(envs[i]->dispose != nullptr);
+ (*envs[i]->dispose)(envs[i]);
+ }
+ std::free(envs);
+ }
+}
+
+ComponentContext::ComponentContext(
+ ContextEntry_Init const * pEntries, sal_Int32 nEntries,
+ Reference< XComponentContext > const & xDelegate )
+ : WeakComponentImplHelper( m_aMutex ),
+ m_xDelegate( xDelegate )
+{
+ for ( sal_Int32 nPos = 0; nPos < nEntries; ++nPos )
+ {
+ ContextEntry_Init const & rEntry = pEntries[ nPos ];
+
+ if ( rEntry.name == SMGR_SINGLETON )
+ {
+ rEntry.value >>= m_xSMgr;
+ }
+
+ if (rEntry.bLateInitService)
+ {
+ // singleton entry
+ m_map.emplace( rEntry.name, ContextEntry( Any(), true ) );
+ // service
+ m_map.emplace( rEntry.name + "/service", ContextEntry( rEntry.value, false ) );
+ // initial-arguments are provided as optional context entry
+ }
+ else
+ {
+ // only value, no late init factory nor string
+ m_map.emplace( rEntry.name, ContextEntry( rEntry.value, false ) );
+ }
+ }
+
+ if (m_xSMgr.is() || !m_xDelegate.is())
+ return;
+
+ // wrap delegate's smgr XPropertySet into new smgr
+ Reference< lang::XMultiComponentFactory > xMgr( m_xDelegate->getServiceManager() );
+ if (!xMgr.is())
+ return;
+
+ osl_atomic_increment( &m_refCount );
+ try
+ {
+ // create new smgr based on delegate's one
+ m_xSMgr.set(
+ xMgr->createInstanceWithContext(
+ "com.sun.star.comp.stoc.OServiceManagerWrapper", xDelegate ),
+ UNO_QUERY );
+ // patch DefaultContext property of new one
+ Reference< beans::XPropertySet > xProps( m_xSMgr, UNO_QUERY );
+ OSL_ASSERT( xProps.is() );
+ if (xProps.is())
+ {
+ Reference< XComponentContext > xThis( this );
+ xProps->setPropertyValue( "DefaultContext", Any( xThis ) );
+ }
+ }
+ catch (...)
+ {
+ osl_atomic_decrement( &m_refCount );
+ throw;
+ }
+ osl_atomic_decrement( &m_refCount );
+ OSL_ASSERT( m_xSMgr.is() );
+}
+
+
+extern "C" { static void s_createComponentContext_v(va_list * pParam)
+{
+ ContextEntry_Init const * pEntries = va_arg(*pParam, ContextEntry_Init const *);
+ sal_Int32 nEntries = va_arg(*pParam, sal_Int32);
+ XComponentContext * pDelegatee = va_arg(*pParam, XComponentContext *);
+ void ** ppContext = va_arg(*pParam, void **);
+ uno::Mapping * pTarget2curr = va_arg(*pParam, uno::Mapping *);
+
+ Reference<XComponentContext> xDelegate(pDelegatee, SAL_NO_ACQUIRE);
+ Reference<XComponentContext> xContext;
+
+ if (nEntries > 0)
+ {
+ try
+ {
+ ComponentContext * p = new ComponentContext( pEntries, nEntries, xDelegate );
+ xContext.set(p);
+ // listen delegate for disposing, to dispose this (wrapping) context first.
+ DisposingForwarder::listen( Reference< lang::XComponent >::query( xDelegate ), p );
+ }
+ catch (Exception & exc)
+ {
+ SAL_WARN( "cppuhelper", exc );
+ xContext.clear();
+ }
+ }
+ else
+ {
+ xContext = xDelegate;
+ }
+
+ *ppContext = pTarget2curr->mapInterface(xContext.get(), cppu::UnoType<decltype(xContext)>::get());
+}}
+
+Reference< XComponentContext > SAL_CALL createComponentContext(
+ ContextEntry_Init const * pEntries, sal_Int32 nEntries,
+ Reference< XComponentContext > const & xDelegate )
+{
+ uno::Environment curr_env(Environment::getCurrent());
+ uno::Environment source_env(CPPU_CURRENT_LANGUAGE_BINDING_NAME);
+
+ uno::Mapping curr2source(curr_env, source_env);
+ uno::Mapping source2curr(source_env, curr_env);
+
+ std::unique_ptr<ContextEntry_Init[]> mapped_entries(new ContextEntry_Init[nEntries]);
+ for (sal_Int32 nPos = 0; nPos < nEntries; ++ nPos)
+ {
+ mapped_entries[nPos].bLateInitService = pEntries[nPos].bLateInitService;
+ mapped_entries[nPos].name = pEntries[nPos].name;
+
+ uno_type_any_constructAndConvert(&mapped_entries[nPos].value,
+ const_cast<void *>(pEntries[nPos].value.getValue()),
+ pEntries[nPos].value.getValueTypeRef(),
+ curr2source.get());
+ }
+
+ void * mapped_delegate = curr2source.mapInterface(xDelegate.get(), cppu::UnoType<decltype(xDelegate)>::get());
+ XComponentContext * pXComponentContext = nullptr;
+ source_env.invoke(s_createComponentContext_v, mapped_entries.get(), nEntries, mapped_delegate, &pXComponentContext, &source2curr);
+ mapped_entries.reset();
+
+ return Reference<XComponentContext>(pXComponentContext, SAL_NO_ACQUIRE);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/defaultbootstrap.cxx b/cppuhelper/source/defaultbootstrap.cxx
new file mode 100644
index 000000000..6e80c9697
--- /dev/null
+++ b/cppuhelper/source/defaultbootstrap.cxx
@@ -0,0 +1,104 @@
+/* -*- 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 <vector>
+
+#include <com/sun/star/uno/DeploymentException.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/lang/XSingleComponentFactory.hpp>
+#include <cppuhelper/bootstrap.hxx>
+#include <cppuhelper/component_context.hxx>
+#include <cppuhelper/weak.hxx>
+#include <rtl/bootstrap.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+
+#include "macro_expander.hxx"
+#include "paths.hxx"
+#include "servicemanager.hxx"
+#include "typemanager.hxx"
+
+namespace com :: sun :: star :: uno { class XComponentContext; }
+
+namespace {
+
+OUString getBootstrapVariable(
+ rtl::Bootstrap const & bootstrap, OUString const & name)
+{
+ OUString v;
+ if (!bootstrap.getFrom(name, v)) {
+ throw css::uno::DeploymentException(
+ "Cannot obtain " + name + " from uno ini");
+ }
+ return v;
+}
+
+}
+
+css::uno::Reference< css::uno::XComponentContext >
+cppu::defaultBootstrap_InitialComponentContext(OUString const & iniUri)
+{
+ rtl::Bootstrap bs(iniUri);
+ if (bs.getHandle() == nullptr) {
+ throw css::uno::DeploymentException(
+ "Cannot open uno ini " + iniUri);
+ }
+ rtl::Reference smgr(
+ new cppuhelper::ServiceManager);
+ smgr->init(getBootstrapVariable(bs, "UNO_SERVICES"));
+ rtl::Reference tmgr(new cppuhelper::TypeManager);
+ tmgr->init(getBootstrapVariable(bs, "UNO_TYPES"));
+ std::vector< cppu::ContextEntry_Init > context_values
+ {
+ cppu::ContextEntry_Init(
+ "/singletons/com.sun.star.lang.theServiceManager",
+ css::uno::Any(
+ css::uno::Reference< css::uno::XInterface >(
+ static_cast< cppu::OWeakObject * >(smgr.get()))),
+ false),
+ cppu::ContextEntry_Init(
+ "/singletons/com.sun.star.reflection.theTypeDescriptionManager",
+ css::uno::Any(
+ css::uno::Reference< css::uno::XInterface >(
+ static_cast< cppu::OWeakObject * >(tmgr.get()))),
+ false),
+ cppu::ContextEntry_Init( //TODO: from services.rdb?
+ "/singletons/com.sun.star.util.theMacroExpander",
+ css::uno::Any(
+ cppuhelper::detail::create_bootstrap_macro_expander_factory()),
+ true)
+ };
+ smgr->addSingletonContextEntries(&context_values);
+ context_values.push_back(
+ cppu::ContextEntry_Init(
+ "/services/com.sun.star.security.AccessController/mode",
+ css::uno::Any(OUString("off")), false));
+ context_values.push_back(
+ cppu::ContextEntry_Init(
+ "/singletons/com.sun.star.security.theAccessController",
+ css::uno::Any(
+ OUString("com.sun.star.security.AccessController")),
+ true));
+ css::uno::Reference< css::uno::XComponentContext > context(
+ createComponentContext(context_values.data(), context_values.size()));
+ smgr->setContext(context);
+ cppu::installTypeDescriptionManager(tmgr);
+ return context;
+}
+
+css::uno::Reference< css::uno::XComponentContext >
+cppu::defaultBootstrap_InitialComponentContext()
+{
+ return defaultBootstrap_InitialComponentContext(getUnoIniUri());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/exc_thrower.cxx b/cppuhelper/source/exc_thrower.cxx
new file mode 100644
index 000000000..57e2ad1d0
--- /dev/null
+++ b/cppuhelper/source/exc_thrower.cxx
@@ -0,0 +1,314 @@
+/* -*- 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 <rtl/instance.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <uno/dispatcher.hxx>
+#include <uno/lbnames.h>
+#include <uno/mapping.hxx>
+#include <cppuhelper/detail/XExceptionThrower.hpp>
+#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
+#include <com/sun/star/ucb/NameClashException.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+
+#include <cppuhelper/exc_hlp.hxx>
+
+using namespace ::osl;
+using namespace ::cppu;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace
+{
+
+using cppuhelper::detail::XExceptionThrower;
+
+
+struct ExceptionThrower : public uno_Interface, XExceptionThrower
+{
+ ExceptionThrower();
+
+ virtual ~ExceptionThrower() {}
+
+ static Type const & getCppuType()
+ {
+ return cppu::UnoType<XExceptionThrower>::get();
+ }
+
+ // XInterface
+ virtual Any SAL_CALL queryInterface( Type const & type ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+ // XExceptionThrower
+ virtual void SAL_CALL throwException( Any const & exc ) override;
+ virtual void SAL_CALL rethrowException() override;
+};
+
+extern "C"
+{
+
+
+void ExceptionThrower_acquire_release_nop(
+ SAL_UNUSED_PARAMETER uno_Interface * )
+{}
+
+
+void ExceptionThrower_dispatch(
+ uno_Interface * pUnoI, typelib_TypeDescription const * pMemberType,
+ void * pReturn, void * pArgs [], uno_Any ** ppException )
+{
+ OSL_ASSERT( pMemberType->eTypeClass == typelib_TypeClass_INTERFACE_METHOD );
+
+ switch (reinterpret_cast< typelib_InterfaceMemberTypeDescription * >(
+ const_cast< typelib_TypeDescription * >( pMemberType ) )->
+ nPosition)
+ {
+ case 0: // queryInterface()
+ {
+ Type const & rType_demanded =
+ *static_cast< Type const * >( pArgs[ 0 ] );
+ if (rType_demanded.equals( cppu::UnoType<XInterface>::get() ) ||
+ rType_demanded.equals( ExceptionThrower::getCppuType() ))
+ {
+ typelib_TypeDescription * pTD = nullptr;
+ TYPELIB_DANGER_GET( &pTD, rType_demanded.getTypeLibType() );
+ uno_any_construct(
+ static_cast< uno_Any * >( pReturn ), &pUnoI, pTD, nullptr );
+ TYPELIB_DANGER_RELEASE( pTD );
+ }
+ else
+ {
+ uno_any_construct(
+ static_cast< uno_Any * >( pReturn ), nullptr, nullptr, nullptr );
+ }
+ *ppException = nullptr;
+ break;
+ }
+ case 1: // acquire()
+ case 2: // release()
+ *ppException = nullptr;
+ break;
+ case 3: // throwException()
+ {
+ uno_Any * pAny = static_cast< uno_Any * >( pArgs[ 0 ] );
+ OSL_ASSERT( pAny->pType->eTypeClass == typelib_TypeClass_EXCEPTION );
+ uno_type_any_construct( *ppException, pAny->pData, pAny->pType, nullptr );
+ break;
+ }
+ default:
+ {
+ OSL_ASSERT( false );
+ RuntimeException exc( "not implemented!" );
+ uno_type_any_construct(
+ *ppException, &exc, cppu::UnoType<decltype(exc)>::get().getTypeLibType(), nullptr );
+ break;
+ }
+ }
+}
+
+} // extern "C"
+
+
+Any ExceptionThrower::queryInterface( Type const & type )
+{
+ if (type.equals( cppu::UnoType<XInterface>::get() ) ||
+ type.equals( ExceptionThrower::getCppuType() ))
+ {
+ XExceptionThrower * that = this;
+ return Any( &that, type );
+ }
+ return Any();
+}
+
+
+void ExceptionThrower::acquire() noexcept
+{
+}
+
+void ExceptionThrower::release() noexcept
+{
+}
+
+
+void ExceptionThrower::throwException( Any const & exc )
+{
+ OSL_FAIL( "unexpected!" );
+ cppu::throwException( exc );
+}
+
+
+void ExceptionThrower::rethrowException()
+{
+ throw;
+}
+
+
+ExceptionThrower::ExceptionThrower()
+{
+ uno_Interface::acquire = ExceptionThrower_acquire_release_nop;
+ uno_Interface::release = ExceptionThrower_acquire_release_nop;
+ uno_Interface::pDispatcher = ExceptionThrower_dispatch;
+}
+
+#if defined(IOS) || defined(ANDROID) || defined(EMSCRIPTEN)
+#define RETHROW_FAKE_EXCEPTIONS 1
+#else
+#define RETHROW_FAKE_EXCEPTIONS 0
+#endif
+
+class theExceptionThrower : public rtl::Static<ExceptionThrower, theExceptionThrower> {};
+
+#if RETHROW_FAKE_EXCEPTIONS
+// In the native iOS / Android app, where we don't have any Java, Python,
+// BASIC, or other scripting, the only thing that would use the C++/UNO bridge
+// functionality that invokes codeSnippet() was cppu::throwException().
+//
+// codeSnippet() is part of what corresponds to the code that uses
+// run-time-generated machine code on other platforms. We can't generate code
+// at run-time on iOS, that has been known forever.
+//
+// Instead of digging in and trying to understand what is wrong, another
+// solution was chosen. It turns out that the number of types of exception
+// objects thrown by cppu::throwException() is fairly small. During startup of
+// the LibreOffice code, and loading of an .odt document, only one kind of
+// exception is thrown this way... (The lovely
+// css::ucb:InteractiveAugmentedIOException.)
+//
+// So we can simply have code that checks what the type of object being thrown
+// is, and explicitly throws such an object then with a normal C++ throw
+// statement. Seems to work.
+template <class E> void tryThrow(css::uno::Any const& aException)
+{
+ E aSpecificException;
+ if (aException >>= aSpecificException)
+ throw aSpecificException;
+}
+
+void lo_mobile_throwException(css::uno::Any const& aException)
+{
+ assert(aException.getValueTypeClass() == css::uno::TypeClass_EXCEPTION);
+
+ tryThrow<css::ucb::InteractiveAugmentedIOException>(aException);
+ tryThrow<css::ucb::NameClashException>(aException);
+ tryThrow<css::uno::RuntimeException>(aException);
+
+ SAL_WARN("cppuhelper", "lo_mobile_throwException: Unhandled exception type: " << aException.getValueTypeName());
+
+ assert(false);
+}
+#endif // RETHROW_FAKE_EXCEPTIONS
+
+} // anonymous namespace
+
+
+namespace cppu
+{
+
+
+void SAL_CALL throwException( Any const & exc )
+{
+ if (exc.getValueTypeClass() != TypeClass_EXCEPTION)
+ {
+ throw RuntimeException(
+ "no UNO exception given "
+ "(must be derived from com::sun::star::uno::Exception)!" );
+ }
+
+#if RETHROW_FAKE_EXCEPTIONS
+ lo_mobile_throwException(exc);
+#else
+ Mapping uno2cpp(Environment(UNO_LB_UNO), Environment::getCurrent());
+ if (! uno2cpp.is())
+ {
+ throw RuntimeException(
+ "cannot get binary UNO to C++ mapping!" );
+ }
+
+ Reference< XExceptionThrower > xThrower;
+ uno2cpp.mapInterface(
+ reinterpret_cast< void ** >( &xThrower ),
+ static_cast< uno_Interface * >( &theExceptionThrower::get() ),
+ ExceptionThrower::getCppuType() );
+ OSL_ASSERT( xThrower.is() );
+ xThrower->throwException( exc );
+#endif // !RETHROW_FAKE_EXCEPTIONS
+}
+
+
+Any SAL_CALL getCaughtException()
+{
+ // why does this differ from RETHROW_FAKE_EXCEPTIONS?
+#if defined(ANDROID) || defined(EMSCRIPTEN)
+ return Any();
+#else
+ Mapping cpp2uno(Environment::getCurrent(), Environment(UNO_LB_UNO));
+ if (! cpp2uno.is())
+ {
+ throw RuntimeException(
+ "cannot get C++ to binary UNO mapping!" );
+ }
+ Mapping uno2cpp(Environment(UNO_LB_UNO), Environment::getCurrent());
+ if (! uno2cpp.is())
+ {
+ throw RuntimeException(
+ "cannot get binary UNO to C++ mapping!" );
+ }
+
+ typelib_TypeDescription * pTD = nullptr;
+ TYPELIB_DANGER_GET(
+ &pTD, ExceptionThrower::getCppuType().getTypeLibType() );
+
+ UnoInterfaceReference unoI;
+ cpp2uno.mapInterface(
+ reinterpret_cast< void ** >( &unoI.m_pUnoI ),
+ static_cast< XExceptionThrower * >( &theExceptionThrower::get() ), pTD );
+ OSL_ASSERT( unoI.is() );
+
+ typelib_TypeDescription * pMemberTD = nullptr;
+ TYPELIB_DANGER_GET(
+ &pMemberTD,
+ reinterpret_cast< typelib_InterfaceTypeDescription * >( pTD )->
+ ppMembers[ 1 ] /* rethrowException() */ );
+
+ uno_Any exc_mem;
+ uno_Any * exc = &exc_mem;
+ unoI.dispatch( pMemberTD, nullptr, nullptr, &exc );
+
+ TYPELIB_DANGER_RELEASE( pMemberTD );
+ TYPELIB_DANGER_RELEASE( pTD );
+
+ if (exc == nullptr)
+ {
+ throw RuntimeException( "rethrowing C++ exception failed!" );
+ }
+
+ Any ret;
+ uno_any_destruct( &ret, reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
+ uno_type_any_constructAndConvert(
+ &ret, exc->pData, exc->pType, uno2cpp.get() );
+ uno_any_destruct( exc, nullptr );
+ return ret;
+#endif
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/factory.cxx b/cppuhelper/source/factory.cxx
new file mode 100644
index 000000000..c8efcab0e
--- /dev/null
+++ b/cppuhelper/source/factory.cxx
@@ -0,0 +1,969 @@
+/* -*- 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/log.hxx>
+#include <osl/diagnose.h>
+#include <osl/mutex.hxx>
+#include <cppuhelper/weak.hxx>
+#include <cppuhelper/component.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <rtl/unload.h>
+
+#include <cppuhelper/propshlp.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/lang/XSingleComponentFactory.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/loader/XImplementationLoader.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/uno/XUnloadingPreference.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+#include <memory>
+#include <utility>
+
+
+using namespace osl;
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::loader;
+using namespace com::sun::star::registry;
+
+namespace cppu
+{
+
+namespace {
+
+class OSingleFactoryHelper
+ : public XServiceInfo
+ , public XSingleServiceFactory
+ , public lang::XSingleComponentFactory
+ , public XUnloadingPreference
+{
+public:
+ OSingleFactoryHelper(
+ const Reference<XMultiServiceFactory > & rServiceManager,
+ OUString aImplementationName_,
+ ComponentInstantiation pCreateFunction_,
+ ComponentFactoryFunc fptr,
+ const Sequence< OUString > * pServiceNames_ )
+ : xSMgr( rServiceManager )
+ , pCreateFunction( pCreateFunction_ )
+ , m_fptr( fptr )
+ , aImplementationName(std::move( aImplementationName_ ))
+ {
+ if( pServiceNames_ )
+ aServiceNames = *pServiceNames_;
+ }
+
+ virtual ~OSingleFactoryHelper();
+
+ // XInterface
+ Any SAL_CALL queryInterface( const Type & rType ) override;
+
+ // XSingleServiceFactory
+ Reference<XInterface > SAL_CALL createInstance() override;
+ virtual Reference<XInterface > SAL_CALL createInstanceWithArguments(const Sequence<Any>& Arguments) override;
+ // XSingleComponentFactory
+ virtual Reference< XInterface > SAL_CALL createInstanceWithContext(
+ Reference< XComponentContext > const & xContext ) override;
+ virtual Reference< XInterface > SAL_CALL createInstanceWithArgumentsAndContext(
+ Sequence< Any > const & rArguments,
+ Reference< XComponentContext > const & xContext ) override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+protected:
+ /**
+ * Create an instance specified by the factory. The one instance logic is implemented
+ * in the createInstance and createInstanceWithArguments methods.
+ * @return the newly created instance. Do not return a previous (one instance) instance.
+ * @throw css::uno::Exception
+ * @throw css::uno::RuntimeException
+ */
+ virtual Reference<XInterface > createInstanceEveryTime(
+ Reference< XComponentContext > const & xContext );
+
+ Reference<XMultiServiceFactory > xSMgr;
+ ComponentInstantiation pCreateFunction;
+ ComponentFactoryFunc m_fptr;
+ Sequence< OUString > aServiceNames;
+ OUString aImplementationName;
+};
+
+}
+
+OSingleFactoryHelper::~OSingleFactoryHelper()
+{
+}
+
+
+Any OSingleFactoryHelper::queryInterface( const Type & rType )
+{
+ return ::cppu::queryInterface(
+ rType,
+ static_cast< XSingleComponentFactory * >( this ),
+ static_cast< XSingleServiceFactory * >( this ),
+ static_cast< XServiceInfo * >( this ) ,
+ static_cast< XUnloadingPreference * >( this ));
+}
+
+// OSingleFactoryHelper
+Reference<XInterface > OSingleFactoryHelper::createInstanceEveryTime(
+ Reference< XComponentContext > const & xContext )
+{
+ if (m_fptr)
+ {
+ return (*m_fptr)( xContext );
+ }
+ if( pCreateFunction )
+ {
+ if (xContext.is())
+ {
+ Reference< lang::XMultiServiceFactory > xContextMgr(
+ xContext->getServiceManager(), UNO_QUERY );
+ if (xContextMgr.is())
+ return (*pCreateFunction)( xContextMgr );
+ }
+ return (*pCreateFunction)( xSMgr );
+ }
+ return Reference< XInterface >();
+}
+
+// XSingleServiceFactory
+Reference<XInterface > OSingleFactoryHelper::createInstance()
+{
+ return createInstanceWithContext( Reference< XComponentContext >() );
+}
+
+// XSingleServiceFactory
+Reference<XInterface > OSingleFactoryHelper::createInstanceWithArguments(
+ const Sequence<Any>& Arguments )
+{
+ return createInstanceWithArgumentsAndContext(
+ Arguments, Reference< XComponentContext >() );
+}
+
+// XSingleComponentFactory
+
+Reference< XInterface > OSingleFactoryHelper::createInstanceWithContext(
+ Reference< XComponentContext > const & xContext )
+{
+ return createInstanceEveryTime( xContext );
+}
+
+Reference< XInterface > OSingleFactoryHelper::createInstanceWithArgumentsAndContext(
+ Sequence< Any > const & rArguments,
+ Reference< XComponentContext > const & xContext )
+{
+ Reference< XInterface > xRet( createInstanceWithContext( xContext ) );
+
+ Reference< lang::XInitialization > xInit( xRet, UNO_QUERY );
+ // always call initialize, even if there are no arguments. #i63511#
+ if (xInit.is())
+ {
+ xInit->initialize( rArguments );
+ }
+ else
+ {
+ if ( rArguments.hasElements() )
+ {
+ // dispose the here created UNO object before throwing out exception
+ // to avoid risk of memory leaks #i113722#
+ Reference<XComponent> xComp( xRet, UNO_QUERY );
+ if (xComp.is())
+ xComp->dispose();
+
+ throw lang::IllegalArgumentException(
+ "cannot pass arguments to component => no XInitialization implemented!",
+ Reference< XInterface >(), 0 );
+ }
+ }
+
+ return xRet;
+}
+
+// XServiceInfo
+OUString OSingleFactoryHelper::getImplementationName()
+{
+ return aImplementationName;
+}
+
+// XServiceInfo
+sal_Bool OSingleFactoryHelper::supportsService(
+ const OUString& ServiceName )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+// XServiceInfo
+Sequence< OUString > OSingleFactoryHelper::getSupportedServiceNames()
+{
+ return aServiceNames;
+}
+
+namespace {
+
+struct OFactoryComponentHelper_Mutex
+{
+ Mutex aMutex;
+};
+
+class OFactoryComponentHelper
+ : public OFactoryComponentHelper_Mutex
+ , public OComponentHelper
+ , public OSingleFactoryHelper
+{
+public:
+ OFactoryComponentHelper(
+ const Reference<XMultiServiceFactory > & rServiceManager,
+ const OUString & rImplementationName_,
+ ComponentInstantiation pCreateFunction_,
+ ComponentFactoryFunc fptr,
+ const Sequence< OUString > * pServiceNames_,
+ bool bOneInstance_ )
+ : OComponentHelper( aMutex )
+ , OSingleFactoryHelper( rServiceManager, rImplementationName_, pCreateFunction_, fptr, pServiceNames_ )
+ , bOneInstance( bOneInstance_ )
+ {
+ }
+
+ // XInterface
+ Any SAL_CALL queryInterface( const Type & rType ) override;
+ void SAL_CALL acquire() noexcept override
+ { OComponentHelper::acquire(); }
+ void SAL_CALL release() noexcept override
+ { OComponentHelper::release(); }
+
+ // XSingleServiceFactory
+ Reference<XInterface > SAL_CALL createInstance() override;
+ Reference<XInterface > SAL_CALL createInstanceWithArguments( const Sequence<Any>& Arguments ) override;
+ // XSingleComponentFactory
+ virtual Reference< XInterface > SAL_CALL createInstanceWithContext(
+ Reference< XComponentContext > const & xContext ) override;
+ virtual Reference< XInterface > SAL_CALL createInstanceWithArgumentsAndContext(
+ Sequence< Any > const & rArguments,
+ Reference< XComponentContext > const & xContext ) override;
+
+ // XTypeProvider
+ virtual Sequence< Type > SAL_CALL getTypes() override;
+ virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+ // XAggregation
+ Any SAL_CALL queryAggregation( const Type & rType ) override;
+
+ // XUnloadingPreference
+ virtual sal_Bool SAL_CALL releaseOnNotification() override;
+
+ // OComponentHelper
+ void SAL_CALL dispose() override;
+
+private:
+ Reference<XInterface > xTheInstance;
+ bool bOneInstance;
+protected:
+ // needed for implementing XUnloadingPreference in inheriting classes
+ bool isOneInstance() const {return bOneInstance;}
+ bool isInstance() const {return xTheInstance.is();}
+};
+
+}
+
+Any SAL_CALL OFactoryComponentHelper::queryInterface( const Type & rType )
+{
+ if( rType == cppu::UnoType<XUnloadingPreference>::get() )
+ {
+ return Any(
+ Reference< XUnloadingPreference >(
+ static_cast< XUnloadingPreference * >(this) ) );
+ }
+ return OComponentHelper::queryInterface( rType );
+}
+
+// XAggregation
+Any OFactoryComponentHelper::queryAggregation( const Type & rType )
+{
+ Any aRet( OComponentHelper::queryAggregation( rType ) );
+ return (aRet.hasValue() ? aRet : OSingleFactoryHelper::queryInterface( rType ));
+}
+
+// XTypeProvider
+Sequence< Type > OFactoryComponentHelper::getTypes()
+{
+ Type ar[ 4 ];
+ ar[ 0 ] = cppu::UnoType<XSingleServiceFactory>::get();
+ ar[ 1 ] = cppu::UnoType<XServiceInfo>::get();
+ ar[ 2 ] = cppu::UnoType<XUnloadingPreference>::get();
+
+ if (m_fptr)
+ ar[ 3 ] = cppu::UnoType<XSingleComponentFactory>::get();
+
+ return Sequence< Type >( ar, m_fptr ? 4 : 3 );
+}
+
+Sequence< sal_Int8 > OFactoryComponentHelper::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// XSingleServiceFactory
+Reference<XInterface > OFactoryComponentHelper::createInstance()
+{
+ if( bOneInstance )
+ {
+ if( !xTheInstance.is() )
+ {
+ MutexGuard aGuard( aMutex );
+ if( !xTheInstance.is() )
+ xTheInstance = OSingleFactoryHelper::createInstance();
+ }
+ return xTheInstance;
+ }
+ return OSingleFactoryHelper::createInstance();
+}
+
+Reference<XInterface > OFactoryComponentHelper::createInstanceWithArguments(
+ const Sequence<Any>& Arguments )
+{
+ if( bOneInstance )
+ {
+ if( !xTheInstance.is() )
+ {
+ MutexGuard aGuard( aMutex );
+// OSL_ENSURE( !xTheInstance.is(), "### arguments will be ignored!" );
+ if( !xTheInstance.is() )
+ xTheInstance = OSingleFactoryHelper::createInstanceWithArguments( Arguments );
+ }
+ return xTheInstance;
+ }
+ return OSingleFactoryHelper::createInstanceWithArguments( Arguments );
+}
+
+// XSingleComponentFactory
+
+Reference< XInterface > OFactoryComponentHelper::createInstanceWithContext(
+ Reference< XComponentContext > const & xContext )
+{
+ if( bOneInstance )
+ {
+ if( !xTheInstance.is() )
+ {
+ MutexGuard aGuard( aMutex );
+// OSL_ENSURE( !xTheInstance.is(), "### context will be ignored!" );
+ if( !xTheInstance.is() )
+ xTheInstance = OSingleFactoryHelper::createInstanceWithContext( xContext );
+ }
+ return xTheInstance;
+ }
+ return OSingleFactoryHelper::createInstanceWithContext( xContext );
+}
+
+Reference< XInterface > OFactoryComponentHelper::createInstanceWithArgumentsAndContext(
+ Sequence< Any > const & rArguments,
+ Reference< XComponentContext > const & xContext )
+{
+ if( bOneInstance )
+ {
+ if( !xTheInstance.is() )
+ {
+ MutexGuard aGuard( aMutex );
+// OSL_ENSURE( !xTheInstance.is(), "### context and arguments will be ignored!" );
+ if( !xTheInstance.is() )
+ xTheInstance = OSingleFactoryHelper::createInstanceWithArgumentsAndContext( rArguments, xContext );
+ }
+ return xTheInstance;
+ }
+ return OSingleFactoryHelper::createInstanceWithArgumentsAndContext( rArguments, xContext );
+}
+
+
+// OComponentHelper
+void OFactoryComponentHelper::dispose()
+{
+ OComponentHelper::dispose();
+
+ Reference<XInterface > x;
+ {
+ // do not delete in the guard section
+ MutexGuard aGuard( aMutex );
+ x = xTheInstance;
+ xTheInstance.clear();
+ }
+ // if it is a component call dispose at the component
+ Reference<XComponent > xComp( x, UNO_QUERY );
+ if( xComp.is() )
+ xComp->dispose();
+}
+
+// XUnloadingPreference
+// This class is used for single factories, component factories and
+// one-instance factories. Depending on the usage this function has
+// to return different values.
+// one-instance factory: sal_False
+// single factory: sal_True
+// component factory: sal_True
+sal_Bool SAL_CALL OFactoryComponentHelper::releaseOnNotification()
+{
+ if( bOneInstance)
+ return false;
+ return true;
+}
+
+namespace {
+
+class ORegistryFactoryHelper : public OFactoryComponentHelper,
+ public OPropertySetHelper
+
+{
+public:
+ ORegistryFactoryHelper(
+ const Reference<XMultiServiceFactory > & rServiceManager,
+ const OUString & rImplementationName_,
+ const Reference<XRegistryKey > & xImplementationKey_,
+ bool bOneInstance_ )
+ : OFactoryComponentHelper(
+ rServiceManager, rImplementationName_, nullptr, nullptr, nullptr, bOneInstance_ ),
+ OPropertySetHelper( OComponentHelper::rBHelper ),
+ xImplementationKey( xImplementationKey_ )
+ {}
+
+ // XInterface
+ virtual Any SAL_CALL queryInterface( Type const & type ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+ // XTypeProvider
+ virtual Sequence< Type > SAL_CALL getTypes() override;
+ // XPropertySet
+ virtual Reference< beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
+
+ // OPropertySetHelper
+ virtual IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+ virtual sal_Bool SAL_CALL convertFastPropertyValue(
+ Any & rConvertedValue, Any & rOldValue,
+ sal_Int32 nHandle, Any const & rValue ) override;
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle, Any const & rValue ) override;
+ using OPropertySetHelper::getFastPropertyValue;
+ virtual void SAL_CALL getFastPropertyValue(
+ Any & rValue, sal_Int32 nHandle ) const override;
+
+ // OSingleFactoryHelper
+ Reference<XInterface > createInstanceEveryTime(
+ Reference< XComponentContext > const & xContext ) override;
+
+ // XSingleServiceFactory
+ Reference<XInterface > SAL_CALL createInstanceWithArguments(const Sequence<Any>& Arguments) override;
+ // XSingleComponentFactory
+ Reference< XInterface > SAL_CALL createInstanceWithArgumentsAndContext(
+ Sequence< Any > const & rArguments,
+ Reference< XComponentContext > const & xContext ) override;
+
+ // XServiceInfo
+ Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+ // XUnloadingPreference
+ sal_Bool SAL_CALL releaseOnNotification() override;
+
+
+private:
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ Reference< XInterface > createModuleFactory();
+
+ /** The registry key of the implementation section */
+ Reference<XRegistryKey > xImplementationKey;
+ /** The factory created with the loader. */
+ Reference<XSingleComponentFactory > xModuleFactory;
+ Reference<XSingleServiceFactory > xModuleFactoryDepr;
+ Reference< beans::XPropertySetInfo > m_xInfo;
+ std::unique_ptr< IPropertyArrayHelper > m_property_array_helper;
+protected:
+ using OPropertySetHelper::getTypes;
+};
+
+}
+
+// XInterface
+
+Any SAL_CALL ORegistryFactoryHelper::queryInterface(
+ Type const & type )
+{
+ Any ret( OFactoryComponentHelper::queryInterface( type ) );
+ if (ret.hasValue())
+ return ret;
+ return OPropertySetHelper::queryInterface( type );
+}
+
+
+void ORegistryFactoryHelper::acquire() noexcept
+{
+ OFactoryComponentHelper::acquire();
+}
+
+
+void ORegistryFactoryHelper::release() noexcept
+{
+ OFactoryComponentHelper::release();
+}
+
+// XTypeProvider
+
+Sequence< Type > ORegistryFactoryHelper::getTypes()
+{
+ Sequence< Type > types( OFactoryComponentHelper::getTypes() );
+ sal_Int32 pos = types.getLength();
+ types.realloc( pos + 3 );
+ Type * p = types.getArray();
+ p[ pos++ ] = cppu::UnoType<beans::XMultiPropertySet>::get();
+ p[ pos++ ] = cppu::UnoType<beans::XFastPropertySet>::get();
+ p[ pos++ ] = cppu::UnoType<beans::XPropertySet>::get();
+ return types;
+}
+
+// XPropertySet
+
+Reference< beans::XPropertySetInfo >
+ORegistryFactoryHelper::getPropertySetInfo()
+{
+ ::osl::MutexGuard guard( aMutex );
+ if (! m_xInfo.is())
+ m_xInfo = createPropertySetInfo( getInfoHelper() );
+ return m_xInfo;
+}
+
+// OPropertySetHelper
+
+IPropertyArrayHelper & ORegistryFactoryHelper::getInfoHelper()
+{
+ ::osl::MutexGuard guard( aMutex );
+ if (m_property_array_helper == nullptr)
+ {
+ beans::Property prop(
+ "ImplementationKey" /* name */,
+ 0 /* handle */,
+ cppu::UnoType<decltype(xImplementationKey)>::get(),
+ beans::PropertyAttribute::READONLY |
+ beans::PropertyAttribute::OPTIONAL );
+ m_property_array_helper.reset(
+ new ::cppu::OPropertyArrayHelper( &prop, 1 ) );
+ }
+ return *m_property_array_helper;
+}
+
+
+sal_Bool ORegistryFactoryHelper::convertFastPropertyValue(
+ Any &, Any &, sal_Int32, Any const & )
+{
+ OSL_FAIL( "unexpected!" );
+ return false;
+}
+
+
+void ORegistryFactoryHelper::setFastPropertyValue_NoBroadcast(
+ sal_Int32, Any const & )
+{
+ throw beans::PropertyVetoException(
+ "unexpected: only readonly properties!",
+ static_cast< OWeakObject * >(this) );
+}
+
+
+void ORegistryFactoryHelper::getFastPropertyValue(
+ Any & rValue, sal_Int32 nHandle ) const
+{
+ if (nHandle == 0)
+ {
+ rValue <<= xImplementationKey;
+ }
+ else
+ {
+ rValue.clear();
+ throw beans::UnknownPropertyException(
+ "unknown property!", static_cast< OWeakObject * >(
+ const_cast< ORegistryFactoryHelper * >(this) ) );
+ }
+}
+
+Reference<XInterface > ORegistryFactoryHelper::createInstanceEveryTime(
+ Reference< XComponentContext > const & xContext )
+{
+ if( !xModuleFactory.is() && !xModuleFactoryDepr.is() )
+ {
+ Reference< XInterface > x( createModuleFactory() );
+ if (x.is())
+ {
+ MutexGuard aGuard( aMutex );
+ if( !xModuleFactory.is() && !xModuleFactoryDepr.is() )
+ {
+ xModuleFactory.set( x, UNO_QUERY );
+ xModuleFactoryDepr.set( x, UNO_QUERY );
+ }
+ }
+ }
+ if( xModuleFactory.is() )
+ {
+ return xModuleFactory->createInstanceWithContext( xContext );
+ }
+ if( xModuleFactoryDepr.is() )
+ {
+ return xModuleFactoryDepr->createInstance();
+ }
+
+ return Reference<XInterface >();
+}
+
+Reference<XInterface > SAL_CALL ORegistryFactoryHelper::createInstanceWithArguments(
+ const Sequence<Any>& Arguments )
+{
+ if( !xModuleFactory.is() && !xModuleFactoryDepr.is() )
+ {
+ Reference< XInterface > x( createModuleFactory() );
+ if (x.is())
+ {
+ MutexGuard aGuard( aMutex );
+ if( !xModuleFactory.is() && !xModuleFactoryDepr.is() )
+ {
+ xModuleFactory.set( x, UNO_QUERY );
+ xModuleFactoryDepr.set( x, UNO_QUERY );
+ }
+ }
+ }
+ if( xModuleFactoryDepr.is() )
+ {
+ return xModuleFactoryDepr->createInstanceWithArguments( Arguments );
+ }
+ if( xModuleFactory.is() )
+ {
+ SAL_INFO("cppuhelper", "no context ORegistryFactoryHelper::createInstanceWithArgumentsAndContext()!");
+ return xModuleFactory->createInstanceWithArgumentsAndContext( Arguments, Reference< XComponentContext >() );
+ }
+
+ return Reference<XInterface >();
+}
+
+Reference< XInterface > ORegistryFactoryHelper::createInstanceWithArgumentsAndContext(
+ Sequence< Any > const & rArguments,
+ Reference< XComponentContext > const & xContext )
+{
+ if( !xModuleFactory.is() && !xModuleFactoryDepr.is() )
+ {
+ Reference< XInterface > x( createModuleFactory() );
+ if (x.is())
+ {
+ MutexGuard aGuard( aMutex );
+ if( !xModuleFactory.is() && !xModuleFactoryDepr.is() )
+ {
+ xModuleFactory.set( x, UNO_QUERY );
+ xModuleFactoryDepr.set( x, UNO_QUERY );
+ }
+ }
+ }
+ if( xModuleFactory.is() )
+ {
+ return xModuleFactory->createInstanceWithArgumentsAndContext( rArguments, xContext );
+ }
+ if( xModuleFactoryDepr.is() )
+ {
+ SAL_INFO_IF(xContext.is(), "cppuhelper", "ignoring context calling ORegistryFactoryHelper::createInstanceWithArgumentsAndContext()!");
+ return xModuleFactoryDepr->createInstanceWithArguments( rArguments );
+ }
+
+ return Reference<XInterface >();
+}
+
+
+// OSingleFactoryHelper
+Reference< XInterface > ORegistryFactoryHelper::createModuleFactory()
+{
+ OUString aActivatorUrl;
+ OUString aActivatorName;
+ OUString aLocation;
+
+ Reference<XRegistryKey > xActivatorKey = xImplementationKey->openKey(
+ "/UNO/ACTIVATOR" );
+ if( xActivatorKey.is() && xActivatorKey->getValueType() == RegistryValueType_ASCII )
+ {
+ aActivatorUrl = xActivatorKey->getAsciiValue();
+
+ aActivatorName = o3tl::getToken(aActivatorUrl, 0, ':');
+
+ Reference<XRegistryKey > xLocationKey = xImplementationKey->openKey(
+ "/UNO/LOCATION" );
+ if( xLocationKey.is() && xLocationKey->getValueType() == RegistryValueType_ASCII )
+ aLocation = xLocationKey->getAsciiValue();
+ }
+ else
+ {
+ // old style"url"
+ // the location of the program code of the implementation
+ Reference<XRegistryKey > xLocationKey = xImplementationKey->openKey(
+ "/UNO/URL" );
+ // is the key of the right type ?
+ if( xLocationKey.is() && xLocationKey->getValueType() == RegistryValueType_ASCII )
+ {
+ // one implementation found -> try to activate
+ aLocation = xLocationKey->getAsciiValue();
+
+ // search protocol delimiter
+ sal_Int32 nPos = aLocation.indexOf("://");
+ if( nPos != -1 )
+ {
+ aActivatorName = aLocation.subView( 0, nPos );
+ if( aActivatorName == u"java" )
+ aActivatorName = u"com.sun.star.loader.Java";
+ else if( aActivatorName == u"module" )
+ aActivatorName = u"com.sun.star.loader.SharedLibrary";
+ aLocation = aLocation.copy( nPos + 3 );
+ }
+ }
+ }
+
+ Reference< XInterface > xFactory;
+ if( !aActivatorName.isEmpty() )
+ {
+ Reference<XInterface > x = xSMgr->createInstance( aActivatorName );
+ Reference<XImplementationLoader > xLoader( x, UNO_QUERY );
+ if (xLoader.is())
+ {
+ xFactory = xLoader->activate( aImplementationName, aActivatorUrl, aLocation, xImplementationKey );
+ }
+ }
+ return xFactory;
+}
+
+// XServiceInfo
+Sequence< OUString > ORegistryFactoryHelper::getSupportedServiceNames()
+{
+ MutexGuard aGuard( aMutex );
+ if( !aServiceNames.hasElements() )
+ {
+ // not yet loaded
+ try
+ {
+ Reference<XRegistryKey > xKey = xImplementationKey->openKey( "UNO/SERVICES" );
+
+ if (xKey.is())
+ {
+ // length of prefix. +1 for the '/' at the end
+ sal_Int32 nPrefixLen = xKey->getKeyName().getLength() + 1;
+
+ // Full qualified names like "IMPLEMENTATIONS/TEST/UNO/SERVICES/com.sun.star..."
+ Sequence<OUString> seqKeys = xKey->getKeyNames();
+ for( OUString & key : asNonConstRange(seqKeys) )
+ key = key.copy(nPrefixLen);
+
+ aServiceNames = seqKeys;
+ }
+ }
+ catch (InvalidRegistryException &)
+ {
+ }
+ }
+ return aServiceNames;
+}
+
+sal_Bool SAL_CALL ORegistryFactoryHelper::releaseOnNotification()
+{
+ bool retVal= true;
+ if( isOneInstance() && isInstance())
+ {
+ retVal= false;
+ }
+ else if( ! isOneInstance())
+ {
+ // try to delegate
+ if( xModuleFactory.is())
+ {
+ Reference<XUnloadingPreference> xunloading( xModuleFactory, UNO_QUERY);
+ if( xunloading.is())
+ retVal= xunloading->releaseOnNotification();
+ }
+ else if( xModuleFactoryDepr.is())
+ {
+ Reference<XUnloadingPreference> xunloading( xModuleFactoryDepr, UNO_QUERY);
+ if( xunloading.is())
+ retVal= xunloading->releaseOnNotification();
+ }
+ }
+ return retVal;
+}
+
+namespace {
+
+class OFactoryProxyHelper : public WeakImplHelper< XServiceInfo, XSingleServiceFactory,
+ XUnloadingPreference >
+{
+ Reference<XSingleServiceFactory > xFactory;
+
+public:
+
+ explicit OFactoryProxyHelper( const Reference<XSingleServiceFactory > & rFactory )
+ : xFactory( rFactory )
+ {}
+
+ // XSingleServiceFactory
+ Reference<XInterface > SAL_CALL createInstance() override;
+ Reference<XInterface > SAL_CALL createInstanceWithArguments(const Sequence<Any>& Arguments) override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+ //XUnloadingPreference
+ sal_Bool SAL_CALL releaseOnNotification() override;
+
+};
+
+}
+
+// XSingleServiceFactory
+Reference<XInterface > OFactoryProxyHelper::createInstance()
+{
+ return xFactory->createInstance();
+}
+
+// XSingleServiceFactory
+Reference<XInterface > OFactoryProxyHelper::createInstanceWithArguments
+(
+ const Sequence<Any>& Arguments
+)
+{
+ return xFactory->createInstanceWithArguments( Arguments );
+}
+
+// XServiceInfo
+OUString OFactoryProxyHelper::getImplementationName()
+{
+ Reference<XServiceInfo > xInfo( xFactory, UNO_QUERY );
+ if( xInfo.is() )
+ return xInfo->getImplementationName();
+ return OUString();
+}
+
+// XServiceInfo
+sal_Bool OFactoryProxyHelper::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+// XServiceInfo
+Sequence< OUString > OFactoryProxyHelper::getSupportedServiceNames()
+{
+ Reference<XServiceInfo > xInfo( xFactory, UNO_QUERY );
+ if( xInfo.is() )
+ return xInfo->getSupportedServiceNames();
+ return Sequence< OUString >();
+}
+
+sal_Bool SAL_CALL OFactoryProxyHelper::releaseOnNotification()
+{
+
+ Reference<XUnloadingPreference> pref( xFactory, UNO_QUERY);
+ if( pref.is())
+ return pref->releaseOnNotification();
+ return true;
+}
+
+// global function
+Reference<XSingleServiceFactory > SAL_CALL createSingleFactory(
+ const Reference<XMultiServiceFactory > & rServiceManager,
+ const OUString & rImplementationName,
+ ComponentInstantiation pCreateFunction,
+ const Sequence< OUString > & rServiceNames,
+ rtl_ModuleCount * )
+{
+ return new OFactoryComponentHelper(
+ rServiceManager, rImplementationName, pCreateFunction, nullptr, &rServiceNames, false );
+}
+
+// global function
+Reference<XSingleServiceFactory > SAL_CALL createFactoryProxy(
+ SAL_UNUSED_PARAMETER const Reference<XMultiServiceFactory > &,
+ const Reference<XSingleServiceFactory > & rFactory )
+{
+ return new OFactoryProxyHelper( rFactory );
+}
+
+// global function
+Reference<XSingleServiceFactory > SAL_CALL createOneInstanceFactory(
+ const Reference<XMultiServiceFactory > & rServiceManager,
+ const OUString & rImplementationName,
+ ComponentInstantiation pCreateFunction,
+ const Sequence< OUString > & rServiceNames,
+ rtl_ModuleCount * )
+{
+ return new OFactoryComponentHelper(
+ rServiceManager, rImplementationName, pCreateFunction, nullptr, &rServiceNames, true );
+}
+
+// global function
+Reference<XSingleServiceFactory > SAL_CALL createSingleRegistryFactory(
+ const Reference<XMultiServiceFactory > & rServiceManager,
+ const OUString & rImplementationName,
+ const Reference<XRegistryKey > & rImplementationKey )
+{
+ return new ORegistryFactoryHelper(
+ rServiceManager, rImplementationName, rImplementationKey, false );
+}
+
+// global function
+Reference<XSingleServiceFactory > SAL_CALL createOneInstanceRegistryFactory(
+ const Reference<XMultiServiceFactory > & rServiceManager,
+ const OUString & rImplementationName,
+ const Reference<XRegistryKey > & rImplementationKey )
+{
+ return new ORegistryFactoryHelper(
+ rServiceManager, rImplementationName, rImplementationKey, true );
+}
+
+
+Reference< lang::XSingleComponentFactory > SAL_CALL createSingleComponentFactory(
+ ComponentFactoryFunc fptr,
+ OUString const & rImplementationName,
+ Sequence< OUString > const & rServiceNames,
+ rtl_ModuleCount *)
+{
+ return new OFactoryComponentHelper(
+ Reference< XMultiServiceFactory >(), rImplementationName, nullptr, fptr, &rServiceNames, false );
+}
+
+Reference< lang::XSingleComponentFactory > SAL_CALL createOneInstanceComponentFactory(
+ ComponentFactoryFunc fptr,
+ OUString const & rImplementationName,
+ Sequence< OUString > const & rServiceNames,
+ rtl_ModuleCount *)
+{
+ return new OFactoryComponentHelper(
+ Reference< XMultiServiceFactory >(), rImplementationName, nullptr, fptr, &rServiceNames, true );
+}
+
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/findsofficepath.c b/cppuhelper/source/findsofficepath.c
new file mode 100644
index 000000000..a46cfb88a
--- /dev/null
+++ b/cppuhelper/source/findsofficepath.c
@@ -0,0 +1,219 @@
+/* -*- 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 <stdlib.h>
+#include <string.h>
+
+#include <cppuhelper/findsofficepath.h>
+
+#if defined(_WIN32)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+/*
+ * Gets the installation path from the Windows Registry for the specified
+ * registry key.
+ *
+ * @param hroot open handle to predefined root registry key
+ * @param subKeyName name of the subkey to open
+ *
+ * @return the installation path or NULL, if no installation was found or
+ * if an error occurred
+ */
+static wchar_t* getPathFromRegistryKey( HKEY hroot, const wchar_t* subKeyName )
+{
+ HKEY hkey;
+ DWORD type;
+ wchar_t* data = NULL;
+ DWORD size;
+
+ /* open the specified registry key */
+ if ( RegOpenKeyExW( hroot, subKeyName, 0, KEY_READ, &hkey ) != ERROR_SUCCESS )
+ {
+ return NULL;
+ }
+
+ /* find the type and size of the default value */
+ if ( RegQueryValueExW( hkey, NULL, NULL, &type, NULL, &size) != ERROR_SUCCESS )
+ {
+ RegCloseKey( hkey );
+ return NULL;
+ }
+
+ /* get memory to hold the default value */
+ data = (wchar_t*) malloc( size + sizeof(wchar_t) );
+
+ /* read the default value */
+ if ( RegQueryValueExW( hkey, NULL, NULL, &type, (LPBYTE) data, &size ) != ERROR_SUCCESS )
+ {
+ RegCloseKey( hkey );
+ free( data );
+ return NULL;
+ }
+
+ // According to https://msdn.microsoft.com/en-us/ms724911, If the data has the REG_SZ,
+ // REG_MULTI_SZ or REG_EXPAND_SZ type, the string may not have been stored with the
+ // proper terminating null characters
+ data[size / sizeof(wchar_t)] = 0;
+
+ /* release registry key handle */
+ RegCloseKey( hkey );
+
+ return data;
+}
+
+/*
+ * Gets the installation path from the Windows Registry.
+ *
+ * @return the installation path or NULL, if no installation was found or
+ * if an error occurred
+ */
+static wchar_t* platformSpecific(void)
+{
+ const wchar_t* UNOPATHVARNAME = L"UNO_PATH";
+
+ /* get the installation path from the UNO_PATH environment variable */
+ wchar_t* env = _wgetenv(UNOPATHVARNAME);
+
+ if (env && env[0])
+ {
+ return wcsdup(env);
+ }
+
+ const wchar_t* SUBKEYNAME = L"Software\\LibreOffice\\UNO\\InstallPath";
+
+ /* read the key's default value from HKEY_CURRENT_USER */
+ wchar_t* path = getPathFromRegistryKey( HKEY_CURRENT_USER, SUBKEYNAME );
+
+ if ( path == NULL )
+ {
+ /* read the key's default value from HKEY_LOCAL_MACHINE */
+ path = getPathFromRegistryKey( HKEY_LOCAL_MACHINE, SUBKEYNAME );
+ }
+
+ return path;
+}
+
+#else
+
+#include <limits.h>
+
+/*
+ * Gets the installation path from the PATH environment variable.
+ *
+ * <p>An installation is found, if the executable 'soffice' or a symbolic link
+ * is in one of the directories listed in the PATH environment variable.</p>
+ *
+ * @return the installation path or NULL, if no installation was found or
+ * if an error occurred
+ */
+static char* platformSpecific(void)
+{
+ const char* UNOPATHVARNAME = "UNO_PATH";
+
+ /* get the installation path from the UNO_PATH environment variable */
+ char* env = getenv(UNOPATHVARNAME);
+
+ const int SEPARATOR = '/';
+ const char* PATHSEPARATOR = ":";
+ const char* PATHVARNAME = "PATH";
+ const char* APPENDIX = "/libreoffice";
+
+ char* path = NULL;
+ char* str = NULL;
+ char* dir = NULL;
+ char* sep = NULL;
+
+ char buffer[PATH_MAX];
+ int pos;
+
+ if (env && env[0])
+ {
+ return strdup(env);
+ }
+
+ /* get the value of the PATH environment variable */
+ env = getenv( PATHVARNAME );
+ if (env == NULL)
+ return NULL;
+
+ str = strdup( env );
+ if (str == NULL)
+ return NULL;
+
+ /* get the tokens separated by ':' */
+ dir = strtok( str, PATHSEPARATOR );
+
+ while ( dir )
+ {
+ /* construct soffice file path */
+ char* resolved = NULL;
+ char* file = (char*) malloc( strlen( dir ) + strlen( APPENDIX ) + 1 );
+ if (file == NULL)
+ {
+ free(str);
+ return NULL;
+ }
+
+ strcpy( file, dir );
+ strcat( file, APPENDIX );
+
+ /* resolve symbolic link */
+ resolved = realpath( file, buffer );
+ if ( resolved != NULL )
+ {
+ /* get path to program directory */
+ sep = strrchr( resolved, SEPARATOR );
+
+ if ( sep != NULL )
+ {
+ pos = sep - resolved;
+ path = (char*) malloc( pos + 1 );
+ strncpy( path, resolved, pos );
+ path[ pos ] = '\0';
+ free( file );
+ break;
+ }
+ }
+
+ dir = strtok( NULL, PATHSEPARATOR );
+ free( file );
+ }
+
+ free( str );
+
+ return path;
+}
+
+#endif
+
+#if defined(_WIN32)
+wchar_t*
+#else
+char*
+#endif
+cppuhelper_detail_findSofficePath(void)
+{
+ return platformSpecific();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/gcc3.map b/cppuhelper/source/gcc3.map
new file mode 100644
index 000000000..2af95d60a
--- /dev/null
+++ b/cppuhelper/source/gcc3.map
@@ -0,0 +1,450 @@
+#
+# 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 .
+#
+UDK_3_0_0 {
+ global:
+ _ZTI*; _ZTS*; # weak RTTI symbols for C++ exceptions
+
+_ZN3com3sun4star3uno19WeakReferenceHelperC1ERKNS2_9ReferenceINS2_10XInterfaceEEE;
+_ZN3com3sun4star3uno19WeakReferenceHelperC1ERKS3_;
+_ZN3com3sun4star3uno19WeakReferenceHelperC2ERKNS2_9ReferenceINS2_10XInterfaceEEE;
+_ZN3com3sun4star3uno19WeakReferenceHelperC2ERKS3_;
+_ZN3com3sun4star3uno19WeakReferenceHelperaSERKS3_;
+_ZN3com3sun4star3uno19WeakReferenceHelperD1Ev;
+_ZN3com3sun4star3uno19WeakReferenceHelperD2Ev;
+_ZN4cppu11OWeakObject12queryAdapterEv;
+_ZN4cppu11OWeakObject14queryInterfaceERKN3com3sun4star3uno4TypeE;
+_ZN4cppu11OWeakObject7acquireEv;
+_ZN4cppu11OWeakObject7releaseEv;
+_ZN4cppu11OWeakObjectD0Ev;
+_ZN4cppu11OWeakObjectD1Ev;
+_ZN4cppu11OWeakObjectD2Ev;
+_ZN4cppu13ClassDataBaseC1E?;
+_ZN4cppu13ClassDataBaseC1Ev;
+_ZN4cppu13ClassDataBaseC2E?;
+_ZN4cppu13ClassDataBaseC2Ev;
+_ZN4cppu13ClassDataBaseD1Ev;
+_ZN4cppu13ClassDataBaseD2Ev;
+_ZN4cppu14OWeakAggObject12setDelegatorERKN3com3sun4star3uno9ReferenceINS4_10XInterfaceEEE;
+_ZN4cppu14OWeakAggObject14queryInterfaceERKN3com3sun4star3uno4TypeE;
+_ZN4cppu14OWeakAggObject16queryAggregationERKN3com3sun4star3uno4TypeE;
+_ZN4cppu14OWeakAggObject7acquireEv;
+_ZN4cppu14OWeakAggObject7releaseEv;
+_ZN4cppu14OWeakAggObjectD0Ev;
+_ZN4cppu14OWeakAggObjectD1Ev;
+_ZN4cppu14OWeakAggObjectD2Ev;
+_ZN4cppu14throwExceptionERKN3com3sun4star3uno3AnyE;
+_ZN4cppu15OTypeCollectionC1ERKN3com3sun4star3uno4TypeERKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC1ERKN3com3sun4star3uno4TypeES7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC1ERKN3com3sun4star3uno4TypeES7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC1ERKN3com3sun4star3uno4TypeES7_S7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC1ERKN3com3sun4star3uno4TypeES7_S7_S7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC1ERKN3com3sun4star3uno4TypeES7_S7_S7_S7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC1ERKN3com3sun4star3uno4TypeES7_S7_S7_S7_S7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC1ERKN3com3sun4star3uno4TypeES7_S7_S7_S7_S7_S7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC1ERKN3com3sun4star3uno4TypeES7_S7_S7_S7_S7_S7_S7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC1ERKN3com3sun4star3uno4TypeES7_S7_S7_S7_S7_S7_S7_S7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC1ERKN3com3sun4star3uno4TypeES7_S7_S7_S7_S7_S7_S7_S7_S7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC1ERKN3com3sun4star3uno4TypeES7_S7_S7_S7_S7_S7_S7_S7_S7_S7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC2ERKN3com3sun4star3uno4TypeERKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC2ERKN3com3sun4star3uno4TypeES7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC2ERKN3com3sun4star3uno4TypeES7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC2ERKN3com3sun4star3uno4TypeES7_S7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC2ERKN3com3sun4star3uno4TypeES7_S7_S7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC2ERKN3com3sun4star3uno4TypeES7_S7_S7_S7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC2ERKN3com3sun4star3uno4TypeES7_S7_S7_S7_S7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC2ERKN3com3sun4star3uno4TypeES7_S7_S7_S7_S7_S7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC2ERKN3com3sun4star3uno4TypeES7_S7_S7_S7_S7_S7_S7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC2ERKN3com3sun4star3uno4TypeES7_S7_S7_S7_S7_S7_S7_S7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC2ERKN3com3sun4star3uno4TypeES7_S7_S7_S7_S7_S7_S7_S7_S7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu15OTypeCollectionC2ERKN3com3sun4star3uno4TypeES7_S7_S7_S7_S7_S7_S7_S7_S7_S7_S7_RKNS4_8SequenceIS5_EE;
+_ZN4cppu16ImplHelper_queryERKN3com3sun4star3uno4TypeEPNS_10class_dataEPv;
+_ZN4cppu16OComponentHelper14queryInterfaceERKN3com3sun4star3uno4TypeE;
+_ZN4cppu16OComponentHelper16addEventListenerERKN3com3sun4star3uno9ReferenceINS3_4lang14XEventListenerEEE;
+_ZN4cppu16OComponentHelper16queryAggregationERKN3com3sun4star3uno4TypeE;
+_ZN4cppu16OComponentHelper19removeEventListenerERKN3com3sun4star3uno9ReferenceINS3_4lang14XEventListenerEEE;
+_ZN4cppu16OComponentHelper7acquireEv;
+_ZN4cppu16OComponentHelper7disposeEv;
+_ZN4cppu16OComponentHelper7releaseEv;
+_ZN4cppu16OComponentHelper8getTypesEv;
+_ZN4cppu16OComponentHelper9disposingEv;
+_ZN4cppu16OComponentHelperC1ERN3osl5MutexE;
+_ZN4cppu16OComponentHelperC2ERN3osl5MutexE;
+_ZN4cppu16OComponentHelperD0Ev;
+_ZN4cppu16OComponentHelperD1Ev;
+_ZN4cppu16OComponentHelperD2Ev;
+_ZN4cppu17OImplementationIdD1Ev;
+_ZN4cppu17OImplementationIdD2Ev;
+_ZN4cppu18OPropertySetHelper14queryInterfaceERKN3com3sun4star3uno4TypeE;
+_ZN4cppu18OPropertySetHelper16getPropertyValueERKN3rtl8OUStringE;
+_ZN4cppu18OPropertySetHelper16setPropertyValueERKN3rtl8OUStringERKN3com3sun4star3uno3AnyE;
+_ZN4cppu18OPropertySetHelper17getPropertyValuesERKN3com3sun4star3uno8SequenceIN3rtl8OUStringEEE;
+_ZN4cppu18OPropertySetHelper17setPropertyValuesERKN3com3sun4star3uno8SequenceIN3rtl8OUStringEEERKNS5_INS4_3AnyEEE;
+_ZN4cppu18OPropertySetHelper20getFastPropertyValueE?;
+_ZN4cppu18OPropertySetHelper20setFastPropertyValueE?RKN3com3sun4star3uno3AnyE;
+_ZN4cppu18OPropertySetHelper21createPropertySetInfoERNS_20IPropertyArrayHelperE;
+_ZN4cppu18OPropertySetHelper21setFastPropertyValuesE?P?PKN3com3sun4star3uno3AnyE?;
+_ZN4cppu18OPropertySetHelper25addPropertyChangeListenerERKN3rtl8OUStringERKN3com3sun4star3uno9ReferenceINS7_5beans23XPropertyChangeListenerEEE;
+_ZN4cppu18OPropertySetHelper25addVetoableChangeListenerERKN3rtl8OUStringERKN3com3sun4star3uno9ReferenceINS7_5beans23XVetoableChangeListenerEEE;
+_ZN4cppu18OPropertySetHelper25firePropertiesChangeEventERKN3com3sun4star3uno8SequenceIN3rtl8OUStringEEERKNS4_9ReferenceINS3_5beans25XPropertiesChangeListenerEEE;
+_ZN4cppu18OPropertySetHelper27addPropertiesChangeListenerERKN3com3sun4star3uno8SequenceIN3rtl8OUStringEEERKNS4_9ReferenceINS3_5beans25XPropertiesChangeListenerEEE;
+_ZN4cppu18OPropertySetHelper28removePropertyChangeListenerERKN3rtl8OUStringERKN3com3sun4star3uno9ReferenceINS7_5beans23XPropertyChangeListenerEEE;
+_ZN4cppu18OPropertySetHelper28removeVetoableChangeListenerERKN3rtl8OUStringERKN3com3sun4star3uno9ReferenceINS7_5beans23XVetoableChangeListenerEEE;
+_ZN4cppu18OPropertySetHelper30removePropertiesChangeListenerERKN3com3sun4star3uno9ReferenceINS3_5beans25XPropertiesChangeListenerEEE;
+_ZN4cppu18OPropertySetHelper4fireEP?PKN3com3sun4star3uno3AnyES8_?h;
+_ZN4cppu18OPropertySetHelper9disposingEv;
+_ZN4cppu18OPropertySetHelperC1ERNS_19OBroadcastHelperVarINS_34OMultiTypeInterfaceContainerHelperEN3com3sun4star3uno4TypeEEE;
+_ZN4cppu18OPropertySetHelperC2ERNS_19OBroadcastHelperVarINS_34OMultiTypeInterfaceContainerHelperEN3com3sun4star3uno4TypeEEE;
+_ZN4cppu18OPropertySetHelperD1Ev;
+_ZN4cppu18OPropertySetHelperD2Ev;
+_ZN4cppu18bootstrapInitialSFERKN3rtl8OUStringE;
+_ZN4cppu18createFactoryProxyERKN3com3sun4star3uno9ReferenceINS2_4lang20XMultiServiceFactoryEEERKNS4_INS5_21XSingleServiceFactoryEEE;
+_ZN4cppu19ImplHelper_getTypesEPNS_10class_dataE;
+_ZN4cppu19createSingleFactoryERKN3com3sun4star3uno9ReferenceINS2_4lang20XMultiServiceFactoryEEERKN3rtl8OUStringEPFNS4_INS3_10XInterfaceEEES9_ERKNS3_8SequenceISB_EEP16_rtl_ModuleCount;
+_ZN4cppu20IPropertyArrayHelperD0Ev;
+_ZN4cppu20IPropertyArrayHelperD1Ev;
+_ZN4cppu20IPropertyArrayHelperD2Ev;
+_ZN4cppu20OPropertyArrayHelper11fillHandlesEP?RKN3com3sun4star3uno8SequenceIN3rtl8OUStringEEE;
+_ZN4cppu20OPropertyArrayHelper13getPropertiesEv;
+_ZN4cppu20OPropertyArrayHelper15getHandleByNameERKN3rtl8OUStringE;
+_ZN4cppu20OPropertyArrayHelper17getPropertyByNameERKN3rtl8OUStringE;
+_ZN4cppu20OPropertyArrayHelper17hasPropertyByNameERKN3rtl8OUStringE;
+_ZN4cppu20OPropertyArrayHelper27fillPropertyMembersByHandleEPN3rtl8OUStringEPs?;
+_ZN4cppu20OPropertyArrayHelper4initEh;
+_ZN4cppu20OPropertyArrayHelperC1EPN3com3sun4star5beans8PropertyE?h;
+_ZN4cppu20OPropertyArrayHelperC1ERKN3com3sun4star3uno8SequenceINS3_5beans8PropertyEEEh;
+_ZN4cppu20OPropertyArrayHelperC2EPN3com3sun4star5beans8PropertyE?h;
+_ZN4cppu20OPropertyArrayHelperC2ERKN3com3sun4star3uno8SequenceINS3_5beans8PropertyEEEh;
+_ZN4cppu20WeakImplHelper_queryERKN3com3sun4star3uno4TypeEPNS_10class_dataEPvPNS_11OWeakObjectE;
+_ZN4cppu20createNestedRegistryERKN3rtl8OUStringE;
+_ZN4cppu20createSimpleRegistryERKN3rtl8OUStringE;
+_ZN4cppu22ImplInhHelper_getTypesEPNS_10class_dataERKN3com3sun4star3uno8SequenceINS5_4TypeEEE;
+_ZN4cppu22createComponentContextEPKNS_17ContextEntry_InitE?RKN3com3sun4star3uno9ReferenceINS6_17XComponentContextEEE;
+_ZN4cppu22getImplHelperInitMutexEv;
+_ZN4cppu23WeakImplHelper_getTypesEPNS_10class_dataE;
+_ZN4cppu24OInterfaceIteratorHelper4nextEv;
+_ZN4cppu24OInterfaceIteratorHelper6removeEv;
+_ZN4cppu24OInterfaceIteratorHelperC1ERNS_25OInterfaceContainerHelperE;
+_ZN4cppu24OInterfaceIteratorHelperC2ERNS_25OInterfaceContainerHelperE;
+_ZN4cppu24OInterfaceIteratorHelperD1Ev;
+_ZN4cppu24OInterfaceIteratorHelperD2Ev;
+_ZN4cppu24createOneInstanceFactoryERKN3com3sun4star3uno9ReferenceINS2_4lang20XMultiServiceFactoryEEERKN3rtl8OUStringEPFNS4_INS3_10XInterfaceEEES9_ERKNS3_8SequenceISB_EEP16_rtl_ModuleCount;
+_ZN4cppu25OInterfaceContainerHelper12addInterfaceERKN3com3sun4star3uno9ReferenceINS4_10XInterfaceEEE;
+_ZN4cppu25OInterfaceContainerHelper15disposeAndClearERKN3com3sun4star4lang11EventObjectE;
+_ZN4cppu25OInterfaceContainerHelper15removeInterfaceERKN3com3sun4star3uno9ReferenceINS4_10XInterfaceEEE;
+_ZN4cppu25OInterfaceContainerHelper17copyAndResetInUseEv;
+_ZN4cppu25OInterfaceContainerHelper5clearEv;
+_ZN4cppu25OInterfaceContainerHelperC1ERN3osl5MutexE;
+_ZN4cppu25OInterfaceContainerHelperC2ERN3osl5MutexE;
+_ZN4cppu25OInterfaceContainerHelperD1Ev;
+_ZN4cppu25OInterfaceContainerHelperD2Ev;
+_ZN4cppu25component_writeInfoHelperEPvS0_PKNS_19ImplementationEntryE;
+_ZN4cppu26WeakAggImplHelper_getTypesEPNS_10class_dataE;
+_ZN4cppu26WeakAggImplHelper_queryAggERKN3com3sun4star3uno4TypeEPNS_10class_dataEPvPNS_14OWeakAggObjectE;
+_ZN4cppu26component_getFactoryHelperEPKcPvS2_PKNS_19ImplementationEntryE;
+_ZN4cppu27WeakComponentImplHelperBase14queryInterfaceERKN3com3sun4star3uno4TypeE;
+_ZN4cppu27WeakComponentImplHelperBase16addEventListenerERKN3com3sun4star3uno9ReferenceINS3_4lang14XEventListenerEEE;
+_ZN4cppu27WeakComponentImplHelperBase19removeEventListenerERKN3com3sun4star3uno9ReferenceINS3_4lang14XEventListenerEEE;
+_ZN4cppu27WeakComponentImplHelperBase7acquireEv;
+_ZN4cppu27WeakComponentImplHelperBase7disposeEv;
+_ZN4cppu27WeakComponentImplHelperBase7releaseEv;
+_ZN4cppu27WeakComponentImplHelperBase9disposingEv;
+_ZN4cppu27WeakComponentImplHelperBaseC1ERN3osl5MutexE;
+_ZN4cppu27WeakComponentImplHelperBaseC2ERN3osl5MutexE;
+_ZN4cppu27WeakComponentImplHelperBaseD0Ev;
+_ZN4cppu27WeakComponentImplHelperBaseD1Ev;
+_ZN4cppu27WeakComponentImplHelperBaseD2Ev;
+_ZN4cppu27createSingleRegistryFactoryERKN3com3sun4star3uno9ReferenceINS2_4lang20XMultiServiceFactoryEEERKN3rtl8OUStringERKNS4_INS2_8registry12XRegistryKeyEEE;
+_ZN4cppu27writeSharedLibComponentInfoERKN3rtl8OUStringES3_RKN3com3sun4star3uno9ReferenceINS6_4lang20XMultiServiceFactoryEEERKNS8_INS6_8registry12XRegistryKeyEEE;
+_ZN4cppu28ImplHelper_queryNoXInterfaceERKN3com3sun4star3uno4TypeEPNS_10class_dataEPv;
+_ZN4cppu28createRegistryServiceFactoryERKN3rtl8OUStringES3_hS3_;
+_ZN4cppu28createSingleComponentFactoryEPFN3com3sun4star3uno9ReferenceINS3_10XInterfaceEEERKNS4_INS3_17XComponentContextEEEERKN3rtl8OUStringERKNS3_8SequenceISE_EEP16_rtl_ModuleCount;
+_ZN4cppu29WeakComponentImplHelper_queryERKN3com3sun4star3uno4TypeEPNS_10class_dataEPvPNS_27WeakComponentImplHelperBaseE;
+_ZN4cppu29installTypeDescriptionManagerERKN3com3sun4star3uno9ReferenceINS2_9container23XHierarchicalNameAccessEEE;
+_ZN4cppu28invokeStaticComponentFactoryEPFvvERKN3rtl8OUStringERKN3com3sun4star3uno9ReferenceINS8_4lang20XMultiServiceFactoryEEERKNSA_INS8_8registry12XRegistryKeyEEES5_;
+_ZN4cppu29loadSharedLibComponentFactoryERKN3rtl8OUStringES3_S3_RKN3com3sun4star3uno9ReferenceINS6_4lang20XMultiServiceFactoryEEERKNS8_INS6_8registry12XRegistryKeyEEE;
+_ZN4cppu29loadSharedLibComponentFactoryERKN3rtl8OUStringES3_S3_RKN3com3sun4star3uno9ReferenceINS6_4lang20XMultiServiceFactoryEEERKNS8_INS6_8registry12XRegistryKeyEEES3_;
+_ZN4cppu30ImplHelper_getImplementationIdEPNS_10class_dataE;
+_ZN4cppu30WeakAggComponentImplHelperBase14queryInterfaceERKN3com3sun4star3uno4TypeE;
+_ZN4cppu30WeakAggComponentImplHelperBase16addEventListenerERKN3com3sun4star3uno9ReferenceINS3_4lang14XEventListenerEEE;
+_ZN4cppu30WeakAggComponentImplHelperBase16queryAggregationERKN3com3sun4star3uno4TypeE;
+_ZN4cppu30WeakAggComponentImplHelperBase19removeEventListenerERKN3com3sun4star3uno9ReferenceINS3_4lang14XEventListenerEEE;
+_ZN4cppu30WeakAggComponentImplHelperBase7acquireEv;
+_ZN4cppu30WeakAggComponentImplHelperBase7disposeEv;
+_ZN4cppu30WeakAggComponentImplHelperBase7releaseEv;
+_ZN4cppu30WeakAggComponentImplHelperBase9disposingEv;
+_ZN4cppu30WeakAggComponentImplHelperBaseC1ERN3osl5MutexE;
+_ZN4cppu30WeakAggComponentImplHelperBaseC2ERN3osl5MutexE;
+_ZN4cppu30WeakAggComponentImplHelperBaseD0Ev;
+_ZN4cppu30WeakAggComponentImplHelperBaseD1Ev;
+_ZN4cppu30WeakAggComponentImplHelperBaseD2Ev;
+_ZN4cppu31createStandardClassWithSequenceERKN3com3sun4star3uno9ReferenceINS2_4lang20XMultiServiceFactoryEEERKN3rtl8OUStringERKNS4_INS2_10reflection9XIdlClassEEERKNS3_8SequenceISB_EE;
+_ZN4cppu32WeakComponentImplHelper_getTypesEPNS_10class_dataE;
+_ZN4cppu32createOneInstanceRegistryFactoryERKN3com3sun4star3uno9ReferenceINS2_4lang20XMultiServiceFactoryEEERKN3rtl8OUStringERKNS4_INS2_8registry12XRegistryKeyEEE;
+_ZN4cppu33bootstrap_InitialComponentContextERKN3com3sun4star3uno9ReferenceINS2_8registry15XSimpleRegistryEEERKN3rtl8OUStringE;
+_ZN4cppu34OMultiTypeInterfaceContainerHelper12addInterfaceERKN3com3sun4star3uno4TypeERKNS4_9ReferenceINS4_10XInterfaceEEE;
+_ZN4cppu34OMultiTypeInterfaceContainerHelper15disposeAndClearERKN3com3sun4star4lang11EventObjectE;
+_ZN4cppu34OMultiTypeInterfaceContainerHelper15removeInterfaceERKN3com3sun4star3uno4TypeERKNS4_9ReferenceINS4_10XInterfaceEEE;
+_ZN4cppu34OMultiTypeInterfaceContainerHelper5clearEv;
+_ZN4cppu34OMultiTypeInterfaceContainerHelperC1ERN3osl5MutexE;
+_ZN4cppu34OMultiTypeInterfaceContainerHelperC2ERN3osl5MutexE;
+_ZN4cppu34OMultiTypeInterfaceContainerHelperD1Ev;
+_ZN4cppu34OMultiTypeInterfaceContainerHelperD2Ev;
+_ZN4cppu35WeakAggComponentImplHelper_getTypesEPNS_10class_dataE;
+_ZN4cppu35WeakAggComponentImplHelper_queryAggERKN3com3sun4star3uno4TypeEPNS_10class_dataEPvPNS_30WeakAggComponentImplHelperBaseE;
+_ZN4cppu39OMultiTypeInterfaceContainerHelperInt3212addInterfaceERK?RKN3com3sun4star3uno9ReferenceINS6_10XInterfaceEEE;
+_ZN4cppu39OMultiTypeInterfaceContainerHelperInt3215disposeAndClearERKN3com3sun4star4lang11EventObjectE;
+_ZN4cppu39OMultiTypeInterfaceContainerHelperInt3215removeInterfaceERK?RKN3com3sun4star3uno9ReferenceINS6_10XInterfaceEEE;
+_ZN4cppu39OMultiTypeInterfaceContainerHelperInt325clearEv;
+_ZN4cppu39OMultiTypeInterfaceContainerHelperInt32C1ERN3osl5MutexE;
+_ZN4cppu39OMultiTypeInterfaceContainerHelperInt32C2ERN3osl5MutexE;
+_ZN4cppu39OMultiTypeInterfaceContainerHelperInt32D1Ev;
+_ZN4cppu39OMultiTypeInterfaceContainerHelperInt32D2Ev;
+_ZN4cppu40defaultBootstrap_InitialComponentContextERKN3rtl8OUStringE;
+_ZN4cppu40defaultBootstrap_InitialComponentContextEv;
+_ZN4cppu9ClassData15writeTypeOffsetERKN3com3sun4star3uno4TypeE?;
+_ZN4cppu9ClassData16initTypeProviderEv;
+_ZN4cppu9ClassData19getImplementationIdEv;
+_ZN4cppu9ClassData5queryERKN3com3sun4star3uno4TypeEPNS3_4lang13XTypeProviderE;
+_ZN4cppu9ClassData8getTypesEv;
+_ZNK3com3sun4star3uno19WeakReferenceHelper3getEv;
+_ZNK4cppu17OImplementationId19getImplementationIdEv;
+_ZNK4cppu20OPropertyArrayHelper8getCountEv;
+_ZNK4cppu25OInterfaceContainerHelper11getElementsEv;
+_ZNK4cppu25OInterfaceContainerHelper9getLengthEv;
+_ZNK4cppu34OMultiTypeInterfaceContainerHelper12getContainerERKN3com3sun4star3uno4TypeE;
+_ZNK4cppu34OMultiTypeInterfaceContainerHelper17getContainedTypesEv;
+_ZNK4cppu39OMultiTypeInterfaceContainerHelperInt3212getContainerERK?;
+_ZNK4cppu39OMultiTypeInterfaceContainerHelperInt3217getContainedTypesEv;
+_ZTVN4cppu11OWeakObjectE;
+_ZTVN4cppu14OWeakAggObjectE;
+_ZTVN4cppu16OComponentHelperE;
+_ZTVN4cppu18OPropertySetHelperE;
+_ZTVN4cppu20IPropertyArrayHelperE;
+_ZTVN4cppu20OPropertyArrayHelperE;
+_ZTVN4cppu27WeakComponentImplHelperBaseE;
+_ZTVN4cppu30WeakAggComponentImplHelperBaseE;
+_ZN4cppu20OPropertyArrayHelperD0Ev;
+_ZN4cppu20OPropertyArrayHelperD1Ev;
+_ZThn*_N4cppu14OWeakAggObject12setDelegatorERKN3com3sun4star3uno9ReferenceINS4_10XInterfaceEEE;
+_ZThn*_N4cppu14OWeakAggObject14queryInterfaceERKN3com3sun4star3uno4TypeE;
+_ZThn*_N4cppu14OWeakAggObject16queryAggregationERKN3com3sun4star3uno4TypeE;
+_ZThn*_N4cppu14OWeakAggObject7acquireEv;
+_ZThn*_N4cppu14OWeakAggObject7releaseEv;
+_ZThn*_N4cppu16OComponentHelper14queryInterfaceERKN3com3sun4star3uno4TypeE;
+_ZThn*_N4cppu16OComponentHelper16queryAggregationERKN3com3sun4star3uno4TypeE;
+_ZThn*_N4cppu16OComponentHelper7acquireEv;
+_ZThn*_N4cppu16OComponentHelper7releaseEv;
+_ZThn*_N4cppu27WeakComponentImplHelperBase14queryInterfaceERKN3com3sun4star3uno4TypeE;
+_ZThn*_N4cppu27WeakComponentImplHelperBase16addEventListenerERKN3com3sun4star3uno9ReferenceINS3_4lang14XEventListenerEEE;
+_ZThn*_N4cppu27WeakComponentImplHelperBase19removeEventListenerERKN3com3sun4star3uno9ReferenceINS3_4lang14XEventListenerEEE;
+_ZThn*_N4cppu27WeakComponentImplHelperBase7acquireEv;
+_ZThn*_N4cppu27WeakComponentImplHelperBase7disposeEv;
+_ZThn*_N4cppu27WeakComponentImplHelperBase7releaseEv;
+_ZThn*_N4cppu30WeakAggComponentImplHelperBase14queryInterfaceERKN3com3sun4star3uno4TypeE;
+_ZThn*_N4cppu30WeakAggComponentImplHelperBase16queryAggregationERKN3com3sun4star3uno4TypeE;
+_ZThn*_N4cppu30WeakAggComponentImplHelperBase7acquireEv;
+_ZThn*_N4cppu30WeakAggComponentImplHelperBase7releaseEv;
+_ZThn*_N4cppu16OComponentHelper14queryInterfaceERKN3com3sun4star3uno4TypeE;
+_ZThn*_N4cppu16OComponentHelper7acquireEv;
+_ZThn*_N4cppu16OComponentHelper7releaseEv;
+_ZThn*_N4cppu16OComponentHelper8getTypesEv;
+_ZThn*_N4cppu30WeakAggComponentImplHelperBase14queryInterfaceERKN3com3sun4star3uno4TypeE;
+_ZThn*_N4cppu30WeakAggComponentImplHelperBase16addEventListenerERKN3com3sun4star3uno9ReferenceINS3_4lang14XEventListenerEEE;
+_ZThn*_N4cppu30WeakAggComponentImplHelperBase19removeEventListenerERKN3com3sun4star3uno9ReferenceINS3_4lang14XEventListenerEEE;
+_ZThn*_N4cppu30WeakAggComponentImplHelperBase7acquireEv;
+_ZThn*_N4cppu30WeakAggComponentImplHelperBase7disposeEv;
+_ZThn*_N4cppu30WeakAggComponentImplHelperBase7releaseEv;
+_ZThn*_N4cppu16OComponentHelper14queryInterfaceERKN3com3sun4star3uno4TypeE;
+_ZThn*_N4cppu16OComponentHelper16addEventListenerERKN3com3sun4star3uno9ReferenceINS3_4lang14XEventListenerEEE;
+_ZThn*_N4cppu16OComponentHelper19removeEventListenerERKN3com3sun4star3uno9ReferenceINS3_4lang14XEventListenerEEE;
+_ZThn*_N4cppu16OComponentHelper7acquireEv;
+_ZThn*_N4cppu16OComponentHelper7disposeEv;
+_ZThn*_N4cppu16OComponentHelper7releaseEv;
+_ZThn*_N4cppu18OPropertySetHelper14queryInterfaceERKN3com3sun4star3uno4TypeE;
+_ZThn*_N4cppu18OPropertySetHelper20getFastPropertyValueE?;
+_ZThn*_N4cppu18OPropertySetHelper20setFastPropertyValueE?RKN3com3sun4star3uno3AnyE;
+_ZThn*_N4cppu18OPropertySetHelper16getPropertyValueERKN3rtl8OUStringE;
+_ZThn*_N4cppu18OPropertySetHelper16setPropertyValueERKN3rtl8OUStringERKN3com3sun4star3uno3AnyE;
+_ZThn*_N4cppu18OPropertySetHelper25addPropertyChangeListenerERKN3rtl8OUStringERKN3com3sun4star3uno9ReferenceINS7_5beans23XPropertyChangeListenerEEE;
+_ZThn*_N4cppu18OPropertySetHelper25addVetoableChangeListenerERKN3rtl8OUStringERKN3com3sun4star3uno9ReferenceINS7_5beans23XVetoableChangeListenerEEE;
+_ZThn*_N4cppu18OPropertySetHelper28removePropertyChangeListenerERKN3rtl8OUStringERKN3com3sun4star3uno9ReferenceINS7_5beans23XPropertyChangeListenerEEE;
+_ZThn*_N4cppu18OPropertySetHelper28removeVetoableChangeListenerERKN3rtl8OUStringERKN3com3sun4star3uno9ReferenceINS7_5beans23XVetoableChangeListenerEEE;
+
+_ZN4cppu13AccessControl19checkFilePermissionERKN3rtl8OUStringES4_;
+_ZN4cppu13AccessControl21checkSocketPermissionERKN3rtl8OUStringES4_;
+_ZN4cppu13AccessControl22checkRuntimePermissionERKN3rtl8OUStringE;
+_ZN4cppu13AccessControlC1ERKN3com3sun4star3uno9ReferenceINS3_8security17XAccessControllerEEE;
+_ZN4cppu13AccessControlC2ERKN3com3sun4star3uno9ReferenceINS3_8security17XAccessControllerEEE;
+_ZN4cppu13AccessControlC1ERKN3com3sun4star3uno9ReferenceINS4_17XComponentContextEEE;
+_ZN4cppu13AccessControlC2ERKN3com3sun4star3uno9ReferenceINS4_17XComponentContextEEE;
+_ZN4cppu13AccessControlC1ERKS0_;
+_ZN4cppu13AccessControlC2ERKS0_;
+
+_ZN4cppu16UnoUrlDescriptorC1ERKN3rtl8OUStringE;
+_ZN4cppu16UnoUrlDescriptorC1ERKS0_;
+_ZN4cppu16UnoUrlDescriptorC2ERKN3rtl8OUStringE;
+_ZN4cppu16UnoUrlDescriptorC2ERKS0_;
+_ZN4cppu16UnoUrlDescriptorD1Ev;
+_ZN4cppu16UnoUrlDescriptorD2Ev;
+_ZN4cppu16UnoUrlDescriptoraSERKS0_;
+_ZN4cppu6UnoUrlC1ERKN3rtl8OUStringE;
+_ZN4cppu6UnoUrlC1ERKS0_;
+_ZN4cppu6UnoUrlC2ERKN3rtl8OUStringE;
+_ZN4cppu6UnoUrlC2ERKS0_;
+_ZN4cppu6UnoUrlD1Ev;
+_ZN4cppu6UnoUrlD2Ev;
+_ZN4cppu6UnoUrlaSERKS0_;
+_ZNK4cppu16UnoUrlDescriptor12getParameterERKN3rtl8OUStringE;
+_ZNK4cppu16UnoUrlDescriptor12hasParameterERKN3rtl8OUStringE;
+_ZNK4cppu16UnoUrlDescriptor13getDescriptorEv;
+_ZNK4cppu16UnoUrlDescriptor7getNameEv;
+_ZNK4cppu6UnoUrl11getProtocolEv;
+_ZNK4cppu6UnoUrl13getConnectionEv;
+_ZNK4cppu6UnoUrl13getObjectNameEv;
+
+ local:
+ *;
+};
+
+UDK_3.1 {
+ global:
+ _ZN4cppu18getCaughtExceptionEv;
+
+ _ZN4cppu18OPropertySetHelperC1ERNS_19OBroadcastHelperVarINS_34OMultiTypeInterfaceContainerHelperEN3com3sun4star3uno4TypeEEEb;
+ _ZN4cppu18OPropertySetHelperC2ERNS_19OBroadcastHelperVarINS_34OMultiTypeInterfaceContainerHelperEN3com3sun4star3uno4TypeEEEb;
+
+ _ZN4cppu9bootstrapEv;
+ _ZN4cppu18BootstrapExceptionC1Ev;
+ _ZN4cppu18BootstrapExceptionC2Ev;
+ _ZN4cppu18BootstrapExceptionC1ERKN3rtl8OUStringE;
+ _ZN4cppu18BootstrapExceptionC2ERKN3rtl8OUStringE;
+ _ZN4cppu18BootstrapExceptionC1ERKS0_;
+ _ZN4cppu18BootstrapExceptionC2ERKS0_;
+ _ZN4cppu18BootstrapExceptionD0Ev;
+ _ZN4cppu18BootstrapExceptionD1Ev;
+ _ZN4cppu18BootstrapExceptionD2Ev;
+ _ZN4cppu18BootstrapExceptionaSERKS0_;
+ _ZNK4cppu18BootstrapException10getMessageEv;
+ # _ZTIN4cppu18BootstrapExceptionE;
+ # _ZTSN4cppu18BootstrapExceptionE;
+} UDK_3_0_0;
+
+UDK_3.2 {
+ global:
+ _ZN4cppu20PropertySetMixinImpl10prepareSetERKN3rtl8OUStringERKN3com3sun4star3uno3AnyESB_PNS0_14BoundListenersE;
+ _ZN4cppu20PropertySetMixinImpl14BoundListenersC1Ev;
+ _ZN4cppu20PropertySetMixinImpl14BoundListenersC2Ev;
+ _ZN4cppu20PropertySetMixinImpl14BoundListenersD1Ev;
+ _ZN4cppu20PropertySetMixinImpl14BoundListenersD2Ev;
+ _ZN4cppu20PropertySetMixinImpl14queryInterfaceERKN3com3sun4star3uno4TypeE;
+ _ZN4cppu20PropertySetMixinImpl16getPropertyValueERKN3rtl8OUStringE;
+ _ZN4cppu20PropertySetMixinImpl16setPropertyValueERKN3rtl8OUStringERKN3com3sun4star3uno3AnyE;
+ _ZN4cppu20PropertySetMixinImpl17getPropertyValuesEv;
+ _ZN4cppu20PropertySetMixinImpl17setPropertyValuesERKN3com3sun4star3uno8SequenceINS3_5beans13PropertyValueEEE;
+ _ZN4cppu20PropertySetMixinImpl18getPropertySetInfoEv;
+ _ZN4cppu20PropertySetMixinImpl20getFastPropertyValueE?;
+ _ZN4cppu20PropertySetMixinImpl20setFastPropertyValueE?RKN3com3sun4star3uno3AnyE;
+ _ZN4cppu20PropertySetMixinImpl25addPropertyChangeListenerERKN3rtl8OUStringERKN3com3sun4star3uno9ReferenceINS7_5beans23XPropertyChangeListenerEEE;
+ _ZN4cppu20PropertySetMixinImpl25addVetoableChangeListenerERKN3rtl8OUStringERKN3com3sun4star3uno9ReferenceINS7_5beans23XVetoableChangeListenerEEE;
+ _ZN4cppu20PropertySetMixinImpl28removePropertyChangeListenerERKN3rtl8OUStringERKN3com3sun4star3uno9ReferenceINS7_5beans23XPropertyChangeListenerEEE;
+ _ZN4cppu20PropertySetMixinImpl28removeVetoableChangeListenerERKN3rtl8OUStringERKN3com3sun4star3uno9ReferenceINS7_5beans23XVetoableChangeListenerEEE;
+ _ZN4cppu20PropertySetMixinImpl7disposeEv;
+ _ZN4cppu20PropertySetMixinImplC1ERKN3com3sun4star3uno9ReferenceINS4_17XComponentContextEEENS0_10ImplementsERKNS4_8SequenceIN3rtl8OUStringEEERKNS4_4TypeE;
+ _ZN4cppu20PropertySetMixinImplC2ERKN3com3sun4star3uno9ReferenceINS4_17XComponentContextEEENS0_10ImplementsERKNS4_8SequenceIN3rtl8OUStringEEERKNS4_4TypeE;
+ _ZN4cppu20PropertySetMixinImplD1Ev;
+ _ZN4cppu20PropertySetMixinImplD2Ev;
+ _ZNK4cppu20PropertySetMixinImpl14BoundListeners6notifyEv;
+ _ZThn*_N4cppu20PropertySetMixinImpl14queryInterfaceERKN3com3sun4star3uno4TypeE;
+ _ZThn*_N4cppu20PropertySetMixinImpl20getFastPropertyValueE?;
+ _ZThn*_N4cppu20PropertySetMixinImpl20setFastPropertyValueE?RKN3com3sun4star3uno3AnyE;
+ _ZThn*_N4cppu20PropertySetMixinImpl14queryInterfaceERKN3com3sun4star3uno4TypeE;
+ _ZThn*_N4cppu20PropertySetMixinImpl17getPropertyValuesEv;
+ _ZThn*_N4cppu20PropertySetMixinImpl17setPropertyValuesERKN3com3sun4star3uno8SequenceINS3_5beans13PropertyValueEEE;
+} UDK_3.1;
+
+UDK_3.3 { # OOo 2.3
+ global:
+ _ZN4cppu18OPropertySetHelper8getTypesEv;
+} UDK_3.2;
+
+UDK_3.4 { # OOo 2.4
+ global:
+ _ZN4cppu19bootstrap_expandUriERKN3rtl8OUStringE; # OUString cppu::bootstrap_expandUri(OUString const &)
+} UDK_3.3;
+
+UDK_3.5 { # OOo 3.0
+ global:
+ _ZN4cppu18OPropertySetHelperC1ERNS_19OBroadcastHelperVarINS_34OMultiTypeInterfaceContainerHelperEN3com3sun4star3uno4TypeEEEPNS_22IEventNotificationHookEb;
+ _ZN4cppu18OPropertySetHelperC2ERNS_19OBroadcastHelperVarINS_34OMultiTypeInterfaceContainerHelperEN3com3sun4star3uno4TypeEEEPNS_22IEventNotificationHookEb;
+} UDK_3.4;
+
+UDK_3.6 { # OOo 3.3
+ global:
+ _ZN4cppu11OWeakObject26disposeWeakConnectionPointEv;
+ _ZN3com3sun4star3uno19WeakReferenceHelperaSERKNS2_9ReferenceINS2_10XInterfaceEEE;
+ _ZN3com3sun4star3uno19WeakReferenceHelper5clearEv;
+ _ZN4cppu33createOneInstanceComponentFactoryEPFN3com3sun4star3uno9ReferenceINS3_10XInterfaceEEERKNS4_INS3_17XComponentContextEEEERKN3rtl8OUStringERKNS3_8SequenceISE_EEP16_rtl_ModuleCount;
+} UDK_3.5;
+
+
+UDK_3.7 { # OOo 3.4
+ global:
+ _ZN4cppu18OPropertySetHelper29setDependentFastPropertyValueE?RKN3com3sun4star3uno3AnyE;
+} UDK_3.6;
+
+UDK_3.8 { # LibO 3.5
+global:
+ ## class OPropertySetHelper2
+ # constructors
+ _ZN4cppu19OPropertySetHelper2C1ERNS_19OBroadcastHelperVarINS_34OMultiTypeInterfaceContainerHelperEN3com3sun4star3uno4TypeEEEPNS_22IEventNotificationHookEb;
+ _ZN4cppu19OPropertySetHelper2C2ERNS_19OBroadcastHelperVarINS_34OMultiTypeInterfaceContainerHelperEN3com3sun4star3uno4TypeEEEPNS_22IEventNotificationHookEb;
+ # destructors
+ _ZN4cppu19OPropertySetHelper2D0Ev;
+ _ZN4cppu19OPropertySetHelper2D1Ev;
+ _ZN4cppu19OPropertySetHelper2D2Ev;
+ # queryInterface
+ _ZN4cppu19OPropertySetHelper214queryInterfaceERKN3com3sun4star3uno4TypeE;
+ _ZThn*_N4cppu19OPropertySetHelper214queryInterfaceERKN3com3sun4star3uno4TypeE;
+ # enableChangeListenerNotification
+ _ZN4cppu19OPropertySetHelper232enableChangeListenerNotificationEh;
+ _ZThn*_N4cppu19OPropertySetHelper232enableChangeListenerNotificationEh;
+} UDK_3.7;
+
+LIBO_UDK_3.9 { # LibO 3.7
+global:
+ _ZN4cppu15supportsServiceEPN3com3sun4star4lang12XServiceInfoERKN3rtl8OUStringE; # cppu::supportsService(com::sun::star::lang::XServiceInfo*, OUString const&)
+} UDK_3.8;
+
+LIBO_UDK_5.3 { # LibO 5.3
+global:
+ _ZN3com3sun4star3uno19WeakReferenceHelperaSEOS3_; # com::sun::star::uno::WeakReferenceHelper::operator=(com::sun::star::uno::WeakReferenceHelper&&)
+} LIBO_UDK_3.9;
+
+LIBO_UDK_7.4 { # LibO 7.4
+global:
+ _ZN3com3sun4star3uno19WeakReferenceHelperaSERKNS2_9ReferenceINS2_5XWeakEEE; # com::sun::star::uno::WeakReferenceHelper::operator=(com::sun::star::uno::Reference<com::sun::star::uno::XWeak> const&)
+ _ZN3com3sun4star3uno19WeakReferenceHelperC1ERKNS2_9ReferenceINS2_5XWeakEEE; # com::sun::star::uno::WeakReferenceHelper::WeakReferenceHelper(com::sun::star::uno::Reference<com::sun::star::uno::XWeak> const&)
+ _ZN3com3sun4star3uno19WeakReferenceHelperC2ERKNS2_9ReferenceINS2_5XWeakEEE; # com::sun::star::uno::WeakReferenceHelper::WeakReferenceHelper(com::sun::star::uno::Reference<com::sun::star::uno::XWeak> const&)
+} LIBO_UDK_5.3;
+
+# Unique libstdc++ symbols:
+GLIBCXX_3.4 {
+ global:
+ _ZGVNSt7num_put*; _ZNSt7num_put*;
+ _ZNSs4_Rep20_S_empty_rep_storageE;
+};
diff --git a/cppuhelper/source/implbase.cxx b/cppuhelper/source/implbase.cxx
new file mode 100644
index 000000000..0673ce692
--- /dev/null
+++ b/cppuhelper/source/implbase.cxx
@@ -0,0 +1,285 @@
+/* -*- 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 <cppuhelper/compbase_ex.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+
+using namespace ::osl;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+namespace cppu
+{
+
+// WeakComponentImplHelperBase
+
+WeakComponentImplHelperBase::WeakComponentImplHelperBase( Mutex & rMutex )
+ : rBHelper( rMutex )
+{
+}
+
+WeakComponentImplHelperBase::~WeakComponentImplHelperBase()
+{
+}
+
+void WeakComponentImplHelperBase::disposing()
+{
+}
+
+Any WeakComponentImplHelperBase::queryInterface( Type const & rType )
+{
+ if (rType == cppu::UnoType<lang::XComponent>::get())
+ {
+ void * p = static_cast< lang::XComponent * >( this );
+ return Any( &p, rType );
+ }
+ return OWeakObject::queryInterface( rType );
+}
+
+void WeakComponentImplHelperBase::acquire()
+ noexcept
+{
+ OWeakObject::acquire();
+}
+
+void WeakComponentImplHelperBase::release()
+ noexcept
+{
+ if (osl_atomic_decrement( &m_refCount ) != 0)
+ return;
+
+ // ensure no other references are created, via the weak connection point, from now on
+ disposeWeakConnectionPoint();
+ // restore reference count:
+ osl_atomic_increment( &m_refCount );
+ if (! rBHelper.bDisposed) {
+ try {
+ dispose();
+ }
+ catch (RuntimeException const& exc) { // don't break throw ()
+ SAL_WARN( "cppuhelper", exc );
+ }
+ OSL_ASSERT( rBHelper.bDisposed );
+ }
+ OWeakObject::release();
+}
+
+void WeakComponentImplHelperBase::dispose()
+{
+ ClearableMutexGuard aGuard( rBHelper.rMutex );
+ if (rBHelper.bDisposed || rBHelper.bInDispose)
+ return;
+
+ rBHelper.bInDispose = true;
+ aGuard.clear();
+ try
+ {
+ // side effect: keeping a reference to this
+ lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
+ try
+ {
+ rBHelper.aLC.disposeAndClear( aEvt );
+ disposing();
+ }
+ catch (...)
+ {
+ MutexGuard aGuard2( rBHelper.rMutex );
+ // bDisposed and bInDispose must be set in this order:
+ rBHelper.bDisposed = true;
+ rBHelper.bInDispose = false;
+ throw;
+ }
+ MutexGuard aGuard2( rBHelper.rMutex );
+ // bDisposed and bInDispose must be set in this order:
+ rBHelper.bDisposed = true;
+ rBHelper.bInDispose = false;
+ }
+ catch (RuntimeException &)
+ {
+ throw;
+ }
+ catch (Exception & exc)
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw lang::WrappedTargetRuntimeException(
+ "unexpected UNO exception caught: " + exc.Message,
+ nullptr, anyEx );
+ }
+}
+
+void WeakComponentImplHelperBase::addEventListener(
+ Reference< lang::XEventListener > const & xListener )
+{
+ ClearableMutexGuard aGuard( rBHelper.rMutex );
+ if (rBHelper.bDisposed || rBHelper.bInDispose)
+ {
+ aGuard.clear();
+ lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
+ xListener->disposing( aEvt );
+ }
+ else
+ {
+ rBHelper.addListener( cppu::UnoType<decltype(xListener)>::get(), xListener );
+ }
+}
+
+void WeakComponentImplHelperBase::removeEventListener(
+ Reference< lang::XEventListener > const & xListener )
+{
+ rBHelper.removeListener( cppu::UnoType<decltype(xListener)>::get(), xListener );
+}
+
+// WeakAggComponentImplHelperBase
+
+WeakAggComponentImplHelperBase::WeakAggComponentImplHelperBase( Mutex & rMutex )
+ : rBHelper( rMutex )
+{
+}
+
+WeakAggComponentImplHelperBase::~WeakAggComponentImplHelperBase()
+{
+}
+
+void WeakAggComponentImplHelperBase::disposing()
+{
+}
+
+Any WeakAggComponentImplHelperBase::queryInterface( Type const & rType )
+{
+ return OWeakAggObject::queryInterface( rType );
+}
+
+Any WeakAggComponentImplHelperBase::queryAggregation( Type const & rType )
+{
+ if (rType == cppu::UnoType<lang::XComponent>::get())
+ {
+ void * p = static_cast< lang::XComponent * >( this );
+ return Any( &p, rType );
+ }
+ return OWeakAggObject::queryAggregation( rType );
+}
+
+void WeakAggComponentImplHelperBase::acquire()
+ noexcept
+{
+ OWeakAggObject::acquire();
+}
+
+void WeakAggComponentImplHelperBase::release()
+ noexcept
+{
+ Reference<XInterface> const xDelegator_(xDelegator);
+ if (xDelegator_.is()) {
+ OWeakAggObject::release();
+ }
+ else if (osl_atomic_decrement( &m_refCount ) == 0) {
+ // ensure no other references are created, via the weak connection point, from now on
+ disposeWeakConnectionPoint();
+ // restore reference count:
+ osl_atomic_increment( &m_refCount );
+ if (! rBHelper.bDisposed) {
+ try {
+ dispose();
+ }
+ catch (RuntimeException const& exc) { // don't break throw ()
+ SAL_WARN( "cppuhelper", exc );
+ }
+ OSL_ASSERT( rBHelper.bDisposed );
+ }
+ OWeakAggObject::release();
+ }
+}
+
+void WeakAggComponentImplHelperBase::dispose()
+{
+ ClearableMutexGuard aGuard( rBHelper.rMutex );
+ if (rBHelper.bDisposed || rBHelper.bInDispose)
+ return;
+
+ rBHelper.bInDispose = true;
+ aGuard.clear();
+ try
+ {
+ // side effect: keeping a reference to this
+ lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
+ try
+ {
+ rBHelper.aLC.disposeAndClear( aEvt );
+ disposing();
+ }
+ catch (...)
+ {
+ MutexGuard aGuard2( rBHelper.rMutex );
+ // bDisposed and bInDispose must be set in this order:
+ rBHelper.bDisposed = true;
+ rBHelper.bInDispose = false;
+ throw;
+ }
+ MutexGuard aGuard2( rBHelper.rMutex );
+ // bDisposed and bInDispose must be set in this order:
+ rBHelper.bDisposed = true;
+ rBHelper.bInDispose = false;
+ }
+ catch (RuntimeException &)
+ {
+ throw;
+ }
+ catch (Exception & exc)
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw lang::WrappedTargetRuntimeException(
+ "unexpected UNO exception caught: " + exc.Message,
+ nullptr, anyEx );
+ }
+}
+
+void WeakAggComponentImplHelperBase::addEventListener(
+ Reference< lang::XEventListener > const & xListener )
+{
+ ClearableMutexGuard aGuard( rBHelper.rMutex );
+ if (rBHelper.bDisposed || rBHelper.bInDispose)
+ {
+ aGuard.clear();
+ lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
+ xListener->disposing( aEvt );
+ }
+ else
+ {
+ rBHelper.addListener( cppu::UnoType<decltype(xListener)>::get(), xListener );
+ }
+}
+
+void WeakAggComponentImplHelperBase::removeEventListener(
+ Reference< lang::XEventListener > const & xListener )
+{
+ // if we have disposed, then we have cleared the list already
+ MutexGuard aGuard( rBHelper.rMutex );
+ if (!rBHelper.bDisposed)
+ rBHelper.removeListener( cppu::UnoType<decltype(xListener)>::get(), xListener );
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/implbase_ex.cxx b/cppuhelper/source/implbase_ex.cxx
new file mode 100644
index 000000000..4ced30adb
--- /dev/null
+++ b/cppuhelper/source/implbase_ex.cxx
@@ -0,0 +1,402 @@
+/* -*- 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 <sal/log.hxx>
+#include <cppuhelper/compbase_ex.hxx>
+#include <cppuhelper/implbase_ex.hxx>
+
+#include <com/sun/star/uno/RuntimeException.hpp>
+
+#include <mutex>
+
+using namespace ::cppu;
+using namespace ::osl;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace cppu
+{
+
+static void checkInterface( Type const & rType )
+{
+ if (TypeClass_INTERFACE != rType.getTypeClass())
+ {
+ OUString msg( "querying for interface \"" + rType.getTypeName() + "\": no interface type!" );
+ SAL_WARN( "cppuhelper", msg );
+ throw RuntimeException( msg );
+ }
+}
+
+static bool isXInterface( rtl_uString * pStr )
+{
+ return OUString::unacquired(&pStr) == "com.sun.star.uno.XInterface";
+}
+
+static void * makeInterface( sal_IntPtr nOffset, void * that )
+{
+ return (static_cast<char *>(that) + nOffset);
+}
+
+static bool td_equals(
+ typelib_TypeDescriptionReference const * pTDR1,
+ typelib_TypeDescriptionReference const * pTDR2 )
+{
+ return ((pTDR1 == pTDR2) ||
+ OUString::unacquired(&pTDR1->pTypeName) == OUString::unacquired(&pTDR2->pTypeName));
+}
+
+static type_entry * getTypeEntries( class_data * cd )
+{
+ 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--; )
+ {
+ type_entry * pEntry = &pEntries[ n ];
+ Type const & rType = (*pEntry->m_type.getCppuType)( nullptr );
+ OSL_ENSURE( rType.getTypeClass() == TypeClass_INTERFACE, "### wrong helper init: expected interface!" );
+ OSL_ENSURE( ! isXInterface( rType.getTypeLibType()->pTypeName ), "### want to implement XInterface: template argument is XInterface?!?!?!" );
+ if (rType.getTypeClass() != TypeClass_INTERFACE)
+ {
+ OUString msg( "type \"" + rType.getTypeName() + "\" is no interface type!" );
+ SAL_WARN( "cppuhelper", msg );
+ throw 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 fillTypes( Type * types, class_data * cd )
+{
+ type_entry * pEntries = getTypeEntries( cd );
+ for ( sal_Int32 n = cd->m_nTypes; n--; )
+ {
+ types[ n ] = pEntries[ n ].m_type.typeRef;
+ }
+}
+
+namespace {
+
+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, class_data * cd, void * that )
+{
+ 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 RuntimeException( msg );
+ }
+ }
+ return nullptr;
+}
+
+// ImplHelper
+
+Any SAL_CALL ImplHelper_query(
+ Type const & rType, class_data * cd, void * that )
+{
+ checkInterface( rType );
+ typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
+
+ void * p;
+ // shortcut for XInterface
+ if (isXInterface( pTDR->pTypeName ))
+ {
+ // take first one
+ p = makeInterface( cd->m_typeEntries[ 0 ].m_offset, that );
+ }
+ else
+ {
+ p = queryDeepNoXInterface( pTDR, cd, that );
+ if (! p)
+ {
+ return Any();
+ }
+ }
+ return Any( &p, pTDR );
+}
+
+Any SAL_CALL ImplHelper_queryNoXInterface(
+ Type const & rType, class_data * cd, void * that )
+{
+ checkInterface( rType );
+ typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
+
+ void * p = queryDeepNoXInterface( pTDR, cd, that );
+ if (p)
+ {
+ return Any( &p, pTDR );
+ }
+ return Any();
+}
+
+css::uno::Sequence<sal_Int8> ImplHelper_getImplementationId(
+ SAL_UNUSED_PARAMETER class_data *)
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+Sequence< Type > SAL_CALL ImplHelper_getTypes(
+ class_data * cd )
+{
+ Sequence< Type > types( cd->m_nTypes );
+ Type * pTypes = types.getArray();
+ fillTypes( pTypes, cd );
+ return types;
+}
+
+Sequence< Type > SAL_CALL ImplInhHelper_getTypes(
+ class_data * cd, Sequence< Type > const & rAddTypes )
+{
+ sal_Int32 nImplTypes = cd->m_nTypes;
+ sal_Int32 nAddTypes = rAddTypes.getLength();
+ Sequence< Type > types( nImplTypes + nAddTypes );
+ Type * pTypes = types.getArray();
+ fillTypes( pTypes, cd );
+ // append base types
+ Type const * pAddTypes = rAddTypes.getConstArray();
+ while (nAddTypes--)
+ {
+ pTypes[ nImplTypes + nAddTypes ] = pAddTypes[ nAddTypes ];
+ }
+ return types;
+}
+
+// WeakImplHelper
+
+Any SAL_CALL WeakImplHelper_query(
+ Type const & rType, class_data * cd, void * that, OWeakObject * pBase )
+{
+ checkInterface( rType );
+ typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
+
+ // shortcut XInterface to OWeakObject
+ if (! isXInterface( pTDR->pTypeName ))
+ {
+ void * p = queryDeepNoXInterface( pTDR, cd, that );
+ if (p)
+ {
+ return Any( &p, pTDR );
+ }
+ }
+ return pBase->OWeakObject::queryInterface( rType );
+}
+
+Sequence< Type > SAL_CALL WeakImplHelper_getTypes(
+ class_data * cd )
+{
+ sal_Int32 nTypes = cd->m_nTypes;
+ Sequence< Type > types( nTypes +1 );
+ Type * pTypes = types.getArray();
+ fillTypes( pTypes, cd );
+ pTypes[ nTypes ] = cppu::UnoType<XWeak>::get();
+ return types;
+}
+
+// WeakAggImplHelper
+
+Any SAL_CALL WeakAggImplHelper_queryAgg(
+ Type const & rType, class_data * cd, void * that, OWeakAggObject * pBase )
+{
+ checkInterface( rType );
+ typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
+
+ // shortcut XInterface to OWeakAggObject
+ if (! isXInterface( pTDR->pTypeName ))
+ {
+ void * p = queryDeepNoXInterface( pTDR, cd, that );
+ if (p)
+ {
+ return Any( &p, pTDR );
+ }
+ }
+ return pBase->OWeakAggObject::queryAggregation( rType );
+}
+
+Sequence< Type > SAL_CALL WeakAggImplHelper_getTypes(
+ class_data * cd )
+{
+ sal_Int32 nTypes = cd->m_nTypes;
+ Sequence< Type > types( nTypes +2 );
+ Type * pTypes = types.getArray();
+ fillTypes( pTypes, cd );
+ pTypes[ nTypes++ ] = cppu::UnoType<XWeak>::get();
+ pTypes[ nTypes ] = cppu::UnoType<XAggregation>::get();
+ return types;
+}
+
+// WeakComponentImplHelper
+
+Any SAL_CALL WeakComponentImplHelper_query(
+ Type const & rType, class_data * cd, void * that, WeakComponentImplHelperBase * pBase )
+{
+ checkInterface( rType );
+ typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
+
+ // shortcut XInterface to WeakComponentImplHelperBase
+ if (! isXInterface( pTDR->pTypeName ))
+ {
+ void * p = queryDeepNoXInterface( pTDR, cd, that );
+ if (p)
+ {
+ return Any( &p, pTDR );
+ }
+ }
+ return pBase->WeakComponentImplHelperBase::queryInterface( rType );
+}
+
+Sequence< Type > SAL_CALL WeakComponentImplHelper_getTypes(
+ class_data * cd )
+{
+ sal_Int32 nTypes = cd->m_nTypes;
+ Sequence< Type > types( nTypes +2 );
+ Type * pTypes = types.getArray();
+ fillTypes( pTypes, cd );
+ pTypes[ nTypes++ ] = cppu::UnoType<XWeak>::get();
+ pTypes[ nTypes ] = cppu::UnoType<lang::XComponent>::get();
+ return types;
+}
+
+// WeakAggComponentImplHelper
+
+Any SAL_CALL WeakAggComponentImplHelper_queryAgg(
+ Type const & rType, class_data * cd, void * that, WeakAggComponentImplHelperBase * pBase )
+{
+ checkInterface( rType );
+ typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
+
+ // shortcut XInterface to WeakAggComponentImplHelperBase
+ if (! isXInterface( pTDR->pTypeName ))
+ {
+ void * p = queryDeepNoXInterface( pTDR, cd, that );
+ if (p)
+ {
+ return Any( &p, pTDR );
+ }
+ }
+ return pBase->WeakAggComponentImplHelperBase::queryAggregation( rType );
+}
+
+Sequence< Type > SAL_CALL WeakAggComponentImplHelper_getTypes(
+ class_data * cd )
+{
+ sal_Int32 nTypes = cd->m_nTypes;
+ Sequence< Type > types( nTypes +3 );
+ Type * pTypes = types.getArray();
+ fillTypes( pTypes, cd );
+ pTypes[ nTypes++ ] = cppu::UnoType<XWeak>::get();
+ pTypes[ nTypes++ ] = cppu::UnoType<XAggregation>::get();
+ pTypes[ nTypes ] = cppu::UnoType<lang::XComponent>::get();
+ return types;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/implementationentry.cxx b/cppuhelper/source/implementationentry.cxx
new file mode 100644
index 000000000..f28547dfa
--- /dev/null
+++ b/cppuhelper/source/implementationentry.cxx
@@ -0,0 +1,94 @@
+/* -*- 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 <cppuhelper/implementationentry.hxx>
+#include <com/sun/star/lang/XSingleComponentFactory.hpp>
+#include <com/sun/star/registry/XRegistryKey.hpp>
+
+#include <osl/diagnose.h>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::registry;
+
+namespace cppu {
+
+sal_Bool component_writeInfoHelper(
+ SAL_UNUSED_PARAMETER void *, void * pRegistryKey,
+ const struct ImplementationEntry entries[])
+{
+ bool bRet = false;
+ try
+ {
+ if( pRegistryKey )
+ {
+ for( sal_Int32 i = 0; entries[i].create ; i ++ )
+ {
+ OUString sKey = "/" + entries[i].getImplementationName() + "/UNO/SERVICES";
+ Reference< XRegistryKey > xNewKey(
+ static_cast< XRegistryKey * >( pRegistryKey )->createKey( sKey ) );
+
+ Sequence< OUString > seq = entries[i].getSupportedServiceNames();
+ const OUString *pArray = seq.getConstArray();
+ for ( sal_Int32 nPos = 0 ; nPos < seq.getLength(); nPos ++ )
+ xNewKey->createKey( pArray[nPos] );
+ }
+ bRet = true;
+ }
+ }
+ catch ( InvalidRegistryException & )
+ {
+ OSL_FAIL( "### InvalidRegistryException!" );
+ }
+ return bRet;
+}
+
+
+void * component_getFactoryHelper(
+ char const * pImplName, SAL_UNUSED_PARAMETER void *,
+ SAL_UNUSED_PARAMETER void *, const struct ImplementationEntry entries[])
+{
+
+ void * pRet = nullptr;
+ Reference< XSingleComponentFactory > xFactory;
+
+ for( sal_Int32 i = 0 ; entries[i].create ; i ++ )
+ {
+ OUString implName = entries[i].getImplementationName();
+ if( implName.equalsAscii( pImplName ) )
+ {
+ xFactory = entries[i].createFactory(
+ entries[i].create,
+ implName,
+ entries[i].getSupportedServiceNames(),
+ entries[i].moduleCounter );
+ }
+ }
+
+ if( xFactory.is() )
+ {
+ xFactory->acquire();
+ pRet = xFactory.get();
+ }
+ return pRet;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/interfacecontainer.cxx b/cppuhelper/source/interfacecontainer.cxx
new file mode 100644
index 000000000..c97a8ba99
--- /dev/null
+++ b/cppuhelper/source/interfacecontainer.cxx
@@ -0,0 +1,596 @@
+/* -*- 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 <cppuhelper/interfacecontainer.hxx>
+#include <cppuhelper/propshlp.hxx>
+#include <comphelper/sequence.hxx>
+
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+#include <osl/mutex.hxx>
+#include <sal/log.hxx>
+
+#include <memory>
+
+#include <com/sun/star/lang/XEventListener.hpp>
+
+
+using namespace osl;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+
+namespace cppu
+{
+
+OInterfaceIteratorHelper::OInterfaceIteratorHelper( OInterfaceContainerHelper & rCont_ )
+ : 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 )
+ {
+ rCont.bInUse = true;
+ nRemain = aData.pAsVector->size();
+ }
+ else if( aData.pAsInterface )
+ {
+ aData.pAsInterface->acquire();
+ nRemain = 1;
+ }
+ else
+ nRemain = 0;
+}
+
+OInterfaceIteratorHelper::~OInterfaceIteratorHelper()
+{
+ bool bShared;
+ {
+ MutexGuard aGuard( rCont.rMutex );
+ // bResetInUse protect the iterator against recursion
+ bShared = aData.pAsVector == rCont.aData.pAsVector && rCont.bIsList;
+ if( bShared )
+ {
+ OSL_ENSURE( rCont.bInUse, "OInterfaceContainerHelper must be in use" );
+ rCont.bInUse = false;
+ }
+ }
+
+ if( !bShared )
+ {
+ if( bIsList )
+ // Sequence owned by the iterator
+ delete aData.pAsVector;
+ else if( aData.pAsInterface )
+ // Interface is acquired by the iterator
+ aData.pAsInterface->release();
+ }
+}
+
+XInterface * OInterfaceIteratorHelper::next()
+{
+ if( nRemain )
+ {
+ nRemain--;
+ if( bIsList )
+ // typecase to const,so the getArray method is faster
+ return (*aData.pAsVector)[nRemain].get();
+ if( aData.pAsInterface )
+ return aData.pAsInterface;
+ }
+ // exception
+ return nullptr;
+}
+
+void OInterfaceIteratorHelper::remove()
+{
+ if( bIsList )
+ {
+ OSL_ASSERT( nRemain >= 0 &&
+ o3tl::make_unsigned(nRemain) < aData.pAsVector->size() );
+ XInterface * p = (*aData.pAsVector)[nRemain].get();
+ rCont.removeInterface( * reinterpret_cast< const Reference< XInterface > * >( &p ) );
+ }
+ else
+ {
+ OSL_ASSERT( 0 == nRemain );
+ rCont.removeInterface( * reinterpret_cast< const Reference< XInterface > * >(&aData.pAsInterface));
+ }
+}
+
+OInterfaceContainerHelper::OInterfaceContainerHelper( Mutex & rMutex_ )
+ : rMutex( rMutex_ )
+ , bInUse( false )
+ , bIsList( false )
+{
+}
+
+OInterfaceContainerHelper::~OInterfaceContainerHelper()
+{
+ OSL_ENSURE( !bInUse, "~OInterfaceContainerHelper but is in use" );
+ if( bIsList )
+ delete aData.pAsVector;
+ else if( aData.pAsInterface )
+ aData.pAsInterface->release();
+}
+
+sal_Int32 OInterfaceContainerHelper::getLength() const
+{
+ MutexGuard aGuard( rMutex );
+ if( bIsList )
+ return aData.pAsVector->size();
+ if( aData.pAsInterface )
+ return 1;
+ return 0;
+}
+
+Sequence< Reference<XInterface> > OInterfaceContainerHelper::getElements() const
+{
+ MutexGuard aGuard( rMutex );
+ if( bIsList )
+ return comphelper::containerToSequence(*aData.pAsVector);
+ if( aData.pAsInterface )
+ {
+ Reference<XInterface> x( aData.pAsInterface );
+ return Sequence< Reference< XInterface > >( &x, 1 );
+ }
+ return Sequence< Reference< XInterface > >();
+}
+
+void OInterfaceContainerHelper::copyAndResetInUse()
+{
+ OSL_ENSURE( bInUse, "OInterfaceContainerHelper not in use" );
+ if( bInUse )
+ {
+ // this should be the worst case. If an iterator is active
+ // and a new Listener is added.
+ if( bIsList )
+ aData.pAsVector= new std::vector< Reference< XInterface > >( *aData.pAsVector );
+ else if( aData.pAsInterface )
+ aData.pAsInterface->acquire();
+
+ bInUse = false;
+ }
+}
+
+sal_Int32 OInterfaceContainerHelper::addInterface( const Reference<XInterface> & rListener )
+{
+ SAL_WARN_IF( !rListener.is(), "cppuhelper", "rListener is empty" );
+ MutexGuard aGuard( rMutex );
+ if( bInUse )
+ copyAndResetInUse();
+
+ if( bIsList )
+ {
+ aData.pAsVector->push_back(rListener);
+ return aData.pAsVector->size();
+ }
+ if( aData.pAsInterface )
+ {
+ Reference<XInterface> tmp(aData.pAsInterface);
+ aData.pAsInterface->release();
+ aData.pAsVector = new std::vector<Reference<XInterface>>(2);
+ (*aData.pAsVector)[0] = std::move(tmp);
+ (*aData.pAsVector)[1] = rListener;
+ bIsList = true;
+ return 2;
+ }
+ aData.pAsInterface = rListener.get();
+ if( rListener.is() )
+ rListener->acquire();
+ return 1;
+}
+
+sal_Int32 OInterfaceContainerHelper::removeInterface( const Reference<XInterface> & rListener )
+{
+ SAL_WARN_IF( !rListener.is(), "cppuhelper", "rListener is empty" );
+ MutexGuard aGuard( rMutex );
+ if( bInUse )
+ copyAndResetInUse();
+
+ if( bIsList )
+ {
+ // It is not valid to compare the pointer directly, but it's faster.
+ auto findIt = std::find_if(aData.pAsVector->begin(), aData.pAsVector->end(),
+ [&](const Reference<XInterface>& r)
+ { return r.get() == rListener.get(); });
+ if (findIt != aData.pAsVector->end())
+ {
+ aData.pAsVector->erase(findIt);
+ }
+ else
+ {
+ // interface not found, use the correct compare method
+ for( auto it = aData.pAsVector->begin(); it != aData.pAsVector->end(); ++it )
+ {
+ if( *it == rListener )
+ {
+ aData.pAsVector->erase(it);
+ break;
+ }
+ }
+ }
+
+ if( aData.pAsVector->size() == 1 )
+ {
+ XInterface * p = (*aData.pAsVector)[0].get();
+ p->acquire();
+ delete aData.pAsVector;
+ aData.pAsInterface = p;
+ bIsList = false;
+ return 1;
+ }
+ return aData.pAsVector->size();
+ }
+ if( aData.pAsInterface && Reference<XInterface>( aData.pAsInterface ) == rListener )
+ {
+ aData.pAsInterface->release();
+ aData.pAsInterface = nullptr;
+ }
+ return aData.pAsInterface ? 1 : 0;
+}
+
+void OInterfaceContainerHelper::disposeAndClear( const EventObject & rEvt )
+{
+ ClearableMutexGuard aGuard( rMutex );
+ OInterfaceIteratorHelper aIt( *this );
+ // Release container, in case new entries come while disposing
+ OSL_ENSURE( !bIsList || bInUse, "OInterfaceContainerHelper not in use" );
+ if( !bIsList && aData.pAsInterface )
+ aData.pAsInterface->release();
+ // set the member to null, use the iterator to delete the values
+ aData.pAsInterface = nullptr;
+ bIsList = false;
+ bInUse = false;
+ aGuard.clear();
+ while( aIt.hasMoreElements() )
+ {
+ try
+ {
+ Reference<XEventListener > xLst( aIt.next(), UNO_QUERY );
+ if( xLst.is() )
+ xLst->disposing( rEvt );
+ }
+ catch ( RuntimeException & )
+ {
+ // be robust, if e.g. a remote bridge has disposed already.
+ // there is no way to delegate the error to the caller :o(.
+ }
+ }
+}
+
+
+void OInterfaceContainerHelper::clear()
+{
+ MutexGuard aGuard( rMutex );
+ // Release container, in case new entries come while disposing
+ OSL_ENSURE( !bIsList || bInUse, "OInterfaceContainerHelper not in use" );
+ if (bInUse)
+ copyAndResetInUse();
+ if (bIsList)
+ delete aData.pAsVector;
+ else if (aData.pAsInterface)
+ aData.pAsInterface->release();
+ aData.pAsInterface = nullptr;
+ bIsList = false;
+}
+
+// specialized class for type
+
+typedef std::vector< std::pair < Type , void* > > t_type2ptr;
+
+OMultiTypeInterfaceContainerHelper::OMultiTypeInterfaceContainerHelper( Mutex & rMutex_ )
+ : rMutex( rMutex_ )
+{
+ m_pMap = new t_type2ptr;
+}
+
+OMultiTypeInterfaceContainerHelper::~OMultiTypeInterfaceContainerHelper()
+{
+ t_type2ptr * pMap = static_cast<t_type2ptr *>(m_pMap);
+
+ for (auto& rItem : *pMap)
+ {
+ delete static_cast<OInterfaceContainerHelper*>(rItem.second);
+ rItem.second = nullptr;
+ }
+ delete pMap;
+}
+
+Sequence< Type > OMultiTypeInterfaceContainerHelper::getContainedTypes() const
+{
+ t_type2ptr * pMap = static_cast<t_type2ptr *>(m_pMap);
+ t_type2ptr::size_type nSize;
+
+ ::osl::MutexGuard aGuard( rMutex );
+ nSize = pMap->size();
+ if( nSize )
+ {
+ css::uno::Sequence< Type > aInterfaceTypes( nSize );
+ Type * pArray = aInterfaceTypes.getArray();
+
+ sal_Int32 i = 0;
+ for (const auto& rItem : *pMap)
+ {
+ // are interfaces added to this container?
+ if( static_cast<OInterfaceContainerHelper*>(rItem.second)->getLength() )
+ // yes, put the type in the array
+ pArray[i++] = rItem.first;
+ }
+ if( static_cast<t_type2ptr::size_type>(i) != nSize ) {
+ // may be empty container, reduce the sequence to the right size
+ aInterfaceTypes = css::uno::Sequence< Type >( pArray, i );
+ }
+ return aInterfaceTypes;
+ }
+ return css::uno::Sequence< Type >();
+}
+
+static t_type2ptr::iterator findType(t_type2ptr *pMap, const Type & rKey )
+{
+ return std::find_if(pMap->begin(), pMap->end(),
+ [&rKey](const t_type2ptr::value_type& rItem) { return rItem.first == rKey; });
+}
+
+OInterfaceContainerHelper * OMultiTypeInterfaceContainerHelper::getContainer( const Type & rKey ) const
+{
+ ::osl::MutexGuard aGuard( rMutex );
+
+ t_type2ptr * pMap = static_cast<t_type2ptr *>(m_pMap);
+ t_type2ptr::iterator iter = findType( pMap, rKey );
+ if( iter != pMap->end() )
+ return static_cast<OInterfaceContainerHelper*>((*iter).second);
+ return nullptr;
+}
+
+sal_Int32 OMultiTypeInterfaceContainerHelper::addInterface(
+ const Type & rKey, const Reference< XInterface > & rListener )
+{
+ ::osl::MutexGuard aGuard( rMutex );
+ t_type2ptr * pMap = static_cast<t_type2ptr *>(m_pMap);
+ t_type2ptr::iterator iter = findType( pMap, rKey );
+ if( iter == pMap->end() )
+ {
+ OInterfaceContainerHelper * pLC = new OInterfaceContainerHelper( rMutex );
+ pMap->push_back(std::pair<Type, void*>(rKey, pLC));
+ return pLC->addInterface( rListener );
+ }
+ return static_cast<OInterfaceContainerHelper*>((*iter).second)->addInterface( rListener );
+}
+
+sal_Int32 OMultiTypeInterfaceContainerHelper::removeInterface(
+ const Type & rKey, const Reference< XInterface > & rListener )
+{
+ ::osl::MutexGuard aGuard( rMutex );
+
+ // search container with id nUik
+ t_type2ptr * pMap = static_cast<t_type2ptr *>(m_pMap);
+ t_type2ptr::iterator iter = findType( pMap, rKey );
+ // container found?
+ if( iter != pMap->end() )
+ return static_cast<OInterfaceContainerHelper*>((*iter).second)->removeInterface( rListener );
+
+ // no container with this id. Always return 0
+ return 0;
+}
+
+void OMultiTypeInterfaceContainerHelper::disposeAndClear( const EventObject & rEvt )
+{
+ t_type2ptr::size_type nSize = 0;
+ std::unique_ptr<OInterfaceContainerHelper *[]> ppListenerContainers;
+ {
+ ::osl::MutexGuard aGuard( rMutex );
+ t_type2ptr * pMap = static_cast<t_type2ptr *>(m_pMap);
+ nSize = pMap->size();
+ if( nSize )
+ {
+ typedef OInterfaceContainerHelper* ppp;
+ ppListenerContainers.reset(new ppp[nSize]);
+ //ppListenerContainers = new (ListenerContainer*)[nSize];
+
+ t_type2ptr::size_type i = 0;
+ for (const auto& rItem : *pMap)
+ {
+ ppListenerContainers[i++] = static_cast<OInterfaceContainerHelper*>(rItem.second);
+ }
+ }
+ }
+
+ // 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 OMultiTypeInterfaceContainerHelper::clear()
+{
+ ::osl::MutexGuard aGuard( rMutex );
+ t_type2ptr * pMap = static_cast<t_type2ptr *>(m_pMap);
+
+ for (auto& rItem : *pMap)
+ {
+ static_cast<OInterfaceContainerHelper*>(rItem.second)->clear();
+ }
+}
+
+// specialized class for long
+
+typedef std::vector< std::pair < sal_Int32 , void* > > t_long2ptr;
+
+static t_long2ptr::iterator findLong(t_long2ptr *pMap, sal_Int32 nKey )
+{
+ return std::find_if(pMap->begin(), pMap->end(),
+ [&nKey](const t_long2ptr::value_type& rItem) { return rItem.first == nKey; });
+}
+
+OMultiTypeInterfaceContainerHelperInt32::OMultiTypeInterfaceContainerHelperInt32( Mutex & rMutex_ )
+ : m_pMap( nullptr )
+ , rMutex( rMutex_ )
+{
+ // delay pMap allocation until necessary.
+}
+
+OMultiTypeInterfaceContainerHelperInt32::~OMultiTypeInterfaceContainerHelperInt32()
+{
+ if (!m_pMap)
+ return;
+
+ t_long2ptr * pMap = static_cast<t_long2ptr *>(m_pMap);
+
+ for (auto& rItem : *pMap)
+ {
+ delete static_cast<OInterfaceContainerHelper*>(rItem.second);
+ rItem.second = nullptr;
+ }
+ delete pMap;
+}
+
+Sequence< sal_Int32 > OMultiTypeInterfaceContainerHelperInt32::getContainedTypes() const
+{
+ t_long2ptr * pMap = static_cast<t_long2ptr *>(m_pMap);
+ t_long2ptr::size_type nSize;
+
+ ::osl::MutexGuard aGuard( rMutex );
+ nSize = pMap ? pMap->size() : 0;
+ if( nSize )
+ {
+ css::uno::Sequence< sal_Int32 > aInterfaceTypes( nSize );
+ sal_Int32 * pArray = aInterfaceTypes.getArray();
+
+ sal_Int32 i = 0;
+ for (const auto& rItem : *pMap)
+ {
+ // are interfaces added to this container?
+ if( static_cast<OInterfaceContainerHelper*>(rItem.second)->getLength() )
+ // yes, put the type in the array
+ pArray[i++] = rItem.first;
+ }
+ if( static_cast<t_long2ptr::size_type>(i) != nSize ) {
+ // may be empty container, reduce the sequence to the right size
+ aInterfaceTypes = css::uno::Sequence< sal_Int32 >( pArray, i );
+ }
+ return aInterfaceTypes;
+ }
+ return css::uno::Sequence< sal_Int32 >();
+}
+
+OInterfaceContainerHelper * OMultiTypeInterfaceContainerHelperInt32::getContainer( const sal_Int32 & rKey ) const
+{
+ ::osl::MutexGuard aGuard( rMutex );
+
+ if (!m_pMap)
+ return nullptr;
+ t_long2ptr * pMap = static_cast<t_long2ptr *>(m_pMap);
+ t_long2ptr::iterator iter = findLong( pMap, rKey );
+ if( iter != pMap->end() )
+ return static_cast<OInterfaceContainerHelper*>((*iter).second);
+ return nullptr;
+}
+
+sal_Int32 OMultiTypeInterfaceContainerHelperInt32::addInterface(
+ const sal_Int32 & rKey, const Reference< XInterface > & rListener )
+{
+ ::osl::MutexGuard aGuard( rMutex );
+ if (!m_pMap)
+ m_pMap = new t_long2ptr;
+ t_long2ptr * pMap = static_cast<t_long2ptr *>(m_pMap);
+ t_long2ptr::iterator iter = findLong( pMap, rKey );
+ if( iter == pMap->end() )
+ {
+ OInterfaceContainerHelper * pLC = new OInterfaceContainerHelper( rMutex );
+ pMap->push_back(std::pair< sal_Int32, void* >(rKey, pLC));
+ return pLC->addInterface( rListener );
+ }
+ return static_cast<OInterfaceContainerHelper*>((*iter).second)->addInterface( rListener );
+}
+
+sal_Int32 OMultiTypeInterfaceContainerHelperInt32::removeInterface(
+ const sal_Int32 & rKey, const Reference< XInterface > & rListener )
+{
+ ::osl::MutexGuard aGuard( rMutex );
+
+ if (!m_pMap)
+ return 0;
+ // search container with id nUik
+ t_long2ptr * pMap = static_cast<t_long2ptr *>(m_pMap);
+ t_long2ptr::iterator iter = findLong( pMap, rKey );
+ // container found?
+ if( iter != pMap->end() )
+ return static_cast<OInterfaceContainerHelper*>((*iter).second)->removeInterface( rListener );
+
+ // no container with this id. Always return 0
+ return 0;
+}
+
+void OMultiTypeInterfaceContainerHelperInt32::disposeAndClear( const EventObject & rEvt )
+{
+ t_long2ptr::size_type nSize = 0;
+ std::unique_ptr<OInterfaceContainerHelper *[]> ppListenerContainers;
+ {
+ ::osl::MutexGuard aGuard( rMutex );
+ if (!m_pMap)
+ return;
+
+ t_long2ptr * pMap = static_cast<t_long2ptr *>(m_pMap);
+ nSize = pMap->size();
+ if( nSize )
+ {
+ typedef OInterfaceContainerHelper* ppp;
+ ppListenerContainers.reset(new ppp[nSize]);
+
+ t_long2ptr::size_type i = 0;
+ for (const auto& rItem : *pMap)
+ {
+ ppListenerContainers[i++] = static_cast<OInterfaceContainerHelper*>(rItem.second);
+ }
+ }
+ }
+
+ // create a copy, because do not fire event in a guarded section
+ for( t_long2ptr::size_type i = 0;
+ i < nSize; i++ )
+ {
+ if( ppListenerContainers[i] )
+ ppListenerContainers[i]->disposeAndClear( rEvt );
+ }
+}
+
+void OMultiTypeInterfaceContainerHelperInt32::clear()
+{
+ ::osl::MutexGuard aGuard( rMutex );
+ if (!m_pMap)
+ return;
+ t_long2ptr * pMap = static_cast<t_long2ptr *>(m_pMap);
+
+ for (auto& rItem : *pMap)
+ {
+ static_cast<OInterfaceContainerHelper*>(rItem.second)->clear();
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/loadsharedlibcomponentfactory.hxx b/cppuhelper/source/loadsharedlibcomponentfactory.hxx
new file mode 100644
index 000000000..d8c7bb555
--- /dev/null
+++ b/cppuhelper/source/loadsharedlibcomponentfactory.hxx
@@ -0,0 +1,41 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <com/sun/star/uno/Reference.hxx>
+
+#include "servicemanager.hxx"
+
+namespace com::sun::star {
+ namespace lang { class XMultiServiceFactory; }
+ namespace uno {
+ class Environment;
+ class XInterface;
+ }
+}
+
+namespace cppuhelper::detail {
+
+css::uno::Environment getEnvironment(
+ OUString const & name, std::u16string_view implementation);
+
+void loadSharedLibComponentFactory(
+ OUString const & uri, OUString const & environment,
+ OUString const & prefix, OUString const & implementation,
+ OUString const & constructor,
+ css::uno::Reference<css::lang::XMultiServiceFactory> const & serviceManager,
+ WrapperConstructorFn * constructorFunction,
+ css::uno::Reference<css::uno::XInterface> * factory);
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/macro_expander.cxx b/cppuhelper/source/macro_expander.cxx
new file mode 100644
index 000000000..93f758bec
--- /dev/null
+++ b/cppuhelper/source/macro_expander.cxx
@@ -0,0 +1,171 @@
+/* -*- 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 <rtl/bootstrap.hxx>
+
+#include <uno/lbnames.h>
+#include <uno/mapping.hxx>
+
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XSingleComponentFactory.hpp>
+#include <com/sun/star/util/XMacroExpander.hpp>
+
+#include "macro_expander.hxx"
+#include "paths.hxx"
+
+constexpr OUStringLiteral SERVICE_NAME_A = u"com.sun.star.lang.MacroExpander";
+constexpr OUStringLiteral SERVICE_NAME_B = u"com.sun.star.lang.BootstrapMacroExpander";
+constexpr OUStringLiteral IMPL_NAME = u"com.sun.star.lang.comp.cppuhelper.BootstrapMacroExpander";
+
+using namespace ::osl;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+using rtl::Bootstrap;
+
+namespace cppu
+{
+
+static Bootstrap const & get_unorc()
+{
+ static rtlBootstrapHandle s_bstrap = rtl_bootstrap_args_open(getUnoIniUri().pData);
+ return *reinterpret_cast<Bootstrap const *>(&s_bstrap);
+}
+
+}
+
+namespace cppuhelper::detail {
+
+OUString expandMacros(OUString const & text) {
+ OUString t(text);
+ rtl_bootstrap_expandMacros_from_handle(
+ cppu::get_unorc().getHandle(), &t.pData);
+ return t;
+}
+
+}
+
+namespace
+{
+
+OUString s_impl_name()
+{
+ return IMPL_NAME;
+}
+
+Sequence< OUString > const & s_get_service_names()
+{
+ static const Sequence< OUString > IMPL_NAMES {
+ SERVICE_NAME_A,
+ SERVICE_NAME_B
+ };
+ return IMPL_NAMES;
+}
+
+typedef cppu::WeakComponentImplHelper<
+ util::XMacroExpander, lang::XServiceInfo > t_uno_impl;
+
+struct mutex_holder
+{
+ Mutex m_mutex;
+};
+
+class Bootstrap_MacroExpander : public mutex_holder, public t_uno_impl
+{
+protected:
+ virtual void SAL_CALL disposing() override;
+
+public:
+ Bootstrap_MacroExpander()
+ : t_uno_impl( m_mutex )
+ {}
+
+ // XMacroExpander impl
+ virtual OUString SAL_CALL expandMacros( OUString const & exp ) override;
+ // XServiceInfo impl
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName ) override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+
+void Bootstrap_MacroExpander::disposing()
+{}
+
+// XServiceInfo impl
+
+OUString Bootstrap_MacroExpander::getImplementationName()
+{
+ return s_impl_name();
+}
+
+sal_Bool Bootstrap_MacroExpander::supportsService( OUString const & serviceName )
+{
+ return cppu::supportsService(this, serviceName);
+}
+
+Sequence< OUString > Bootstrap_MacroExpander::getSupportedServiceNames()
+{
+ return s_get_service_names();
+}
+
+// XMacroExpander impl
+
+OUString Bootstrap_MacroExpander::expandMacros( OUString const & exp )
+{
+ return cppuhelper::detail::expandMacros( exp );
+}
+
+
+Reference< XInterface > service_create(
+ SAL_UNUSED_PARAMETER Reference< XComponentContext > const & )
+{
+ return static_cast< ::cppu::OWeakObject * >( new Bootstrap_MacroExpander );
+}
+
+}
+
+namespace cppuhelper::detail {
+
+Reference< lang::XSingleComponentFactory > create_bootstrap_macro_expander_factory()
+{
+ Reference< lang::XSingleComponentFactory > free(::cppu::createSingleComponentFactory(
+ service_create,
+ s_impl_name(),
+ s_get_service_names() ));
+
+ uno::Environment curr_env(Environment::getCurrent());
+ uno::Environment target_env(CPPU_CURRENT_LANGUAGE_BINDING_NAME);
+
+ uno::Mapping target2curr(target_env, curr_env);
+
+ return Reference<lang::XSingleComponentFactory>(
+ static_cast<lang::XSingleComponentFactory *>(
+ target2curr.mapInterface(free.get(), cppu::UnoType<decltype(free)>::get())),
+ SAL_NO_ACQUIRE);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/macro_expander.hxx b/cppuhelper/source/macro_expander.hxx
new file mode 100644
index 000000000..11736656c
--- /dev/null
+++ b/cppuhelper/source/macro_expander.hxx
@@ -0,0 +1,56 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <com/sun/star/uno/Reference.hxx>
+
+namespace com::sun::star::lang { class XSingleComponentFactory; }
+
+namespace cppuhelper {
+
+namespace detail {
+
+/**
+ * Helper function to expand macros based on the unorc/uno.ini.
+ *
+ * @internal
+ *
+ * @param text
+ * Some text.
+ *
+ * @return
+ * The expanded text.
+ *
+ * @exception com::sun::star::lang::IllegalArgumentException
+ * If uriReference is a vnd.sun.star.expand URL reference that contains unknown
+ * macros.
+ */
+OUString expandMacros(OUString const & text);
+
+css::uno::Reference< css::lang::XSingleComponentFactory >
+create_bootstrap_macro_expander_factory();
+
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/paths.cxx b/cppuhelper/source/paths.cxx
new file mode 100644
index 000000000..dd8fe56df
--- /dev/null
+++ b/cppuhelper/source/paths.cxx
@@ -0,0 +1,135 @@
+/* -*- 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 <config_folders.h>
+
+#include <sal/config.h>
+
+#include <cassert>
+
+#include <com/sun/star/uno/DeploymentException.hpp>
+#include <osl/file.hxx>
+#include <osl/module.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+#include <o3tl/string_view.hxx>
+
+#include "paths.hxx"
+
+namespace {
+
+#if !(defined ANDROID || defined EMSCRIPTEN)
+OUString get_this_libpath() {
+ static OUString s_uri = []() {
+ OUString uri;
+ osl::Module::getUrlFromAddress(reinterpret_cast<oslGenericFunction>(get_this_libpath), uri);
+ sal_Int32 i = uri.lastIndexOf('/');
+ if (i == -1)
+ {
+ throw css::uno::DeploymentException("URI " + uri + " is expected to contain a slash");
+ }
+ return uri.copy(0, i);
+ }();
+
+ return s_uri;
+}
+#endif
+}
+
+OUString cppu::getUnoIniUri() {
+#if defined ANDROID
+ // Wouldn't it be lovely to avoid this ugly hard-coding.
+ // The problem is that the 'create_bootstrap_macro_expander_factory()'
+ // required for bootstrapping services, calls cppu::get_unorc directly
+ // instead of re-using the BootstrapHandle from:
+ // defaultBootstrap_InitialComponentContext
+ // and since rtlBootstrapHandle is not ref-counted doing anything
+ // clean here is hardish.
+ OUString uri("file:///assets/program");
+#elif defined(EMSCRIPTEN)
+ OUString uri("file:///instdir/program");
+#else
+ OUString uri(get_this_libpath());
+#ifdef MACOSX
+ // We keep the URE dylibs directly in "Frameworks" (that is, LIBO_LIB_FOLDER) and unorc in
+ // "Resources/ure/etc" (LIBO_URE_ETC_FOLDER).
+ if (uri.endsWith( "/" LIBO_LIB_FOLDER ) )
+ {
+ uri = OUString::Concat(uri.subView( 0, uri.getLength() - (sizeof(LIBO_LIB_FOLDER)-1) )) + LIBO_URE_ETC_FOLDER;
+ }
+#endif
+#endif
+ return uri + "/" SAL_CONFIGFILE("uno");
+}
+
+bool cppu::nextDirectoryItem(osl::Directory & directory, OUString * url) {
+ assert(url != nullptr);
+ for (;;) {
+ osl::DirectoryItem i;
+ switch (directory.getNextItem(i, SAL_MAX_UINT32)) {
+ case osl::FileBase::E_None:
+ break;
+ case osl::FileBase::E_NOENT:
+ return false;
+ default:
+ throw css::uno::DeploymentException(
+ "Cannot iterate directory");
+ }
+ osl::FileStatus stat(
+ osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName |
+ osl_FileStatus_Mask_FileURL);
+ if (i.getFileStatus(stat) != osl::FileBase::E_None) {
+ throw css::uno::DeploymentException(
+ "Cannot stat in directory");
+ }
+ if (stat.getFileType() != osl::FileStatus::Directory) { //TODO: symlinks
+ // Ignore backup and spurious junk files:
+ OUString name(stat.getFileName());
+ if (name.match(".") || !name.endsWithIgnoreAsciiCase(u".rdb")) {
+ SAL_WARN("cppuhelper", "ignoring <" << stat.getFileURL() << ">");
+ } else {
+ *url = stat.getFileURL();
+ return true;
+ }
+ }
+ }
+}
+
+void cppu::decodeRdbUri(std::u16string_view * uri, bool * optional, bool * directory)
+{
+ assert(uri != nullptr && optional != nullptr && directory != nullptr);
+ if(!(uri->empty()))
+ {
+ *optional = (*uri)[0] == '?';
+ if (*optional) {
+ *uri = uri->substr(1);
+ }
+ *directory = o3tl::starts_with(*uri, u"<") && o3tl::ends_with(*uri, u">*");
+ if (*directory) {
+ *uri = uri->substr(1, uri->size() - 3);
+ }
+ }
+ else
+ {
+ *optional = false;
+ *directory = false;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/paths.hxx b/cppuhelper/source/paths.hxx
new file mode 100644
index 000000000..b46810489
--- /dev/null
+++ b/cppuhelper/source/paths.hxx
@@ -0,0 +1,40 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+#include <rtl/ustring.hxx>
+#include <string_view>
+
+namespace osl
+{
+class Directory;
+}
+
+namespace cppu
+{
+OUString getUnoIniUri();
+
+bool nextDirectoryItem(osl::Directory& directory, OUString* url);
+
+void decodeRdbUri(std::u16string_view* uri, bool* optional, bool* directory);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/propertysetmixin.cxx b/cppuhelper/source/propertysetmixin.cxx
new file mode 100644
index 000000000..0d94e7a82
--- /dev/null
+++ b/cppuhelper/source/propertysetmixin.cxx
@@ -0,0 +1,1143 @@
+/* -*- 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 <algorithm>
+#include <cassert>
+#include <map>
+#include <mutex>
+#include <set>
+#include <utility>
+#include <vector>
+
+#include <com/sun/star/beans/Property.hpp>
+#include <com/sun/star/beans/PropertyChangeEvent.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/PropertyVetoException.hpp>
+#include <com/sun/star/beans/UnknownPropertyException.hpp>
+#include <com/sun/star/beans/XFastPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyAccess.hpp>
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/beans/XVetoableChangeListener.hpp>
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/EventObject.hpp>
+#include <com/sun/star/lang/IllegalAccessException.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/reflection/XCompoundTypeDescription.hpp>
+#include <com/sun/star/reflection/XIdlClass.hpp>
+#include <com/sun/star/reflection/XIdlField2.hpp>
+#include <com/sun/star/reflection/XIndirectTypeDescription.hpp>
+#include <com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp>
+#include <com/sun/star/reflection/XInterfaceMemberTypeDescription.hpp>
+#include <com/sun/star/reflection/XInterfaceTypeDescription2.hpp>
+#include <com/sun/star/reflection/XStructTypeDescription.hpp>
+#include <com/sun/star/reflection/XTypeDescription.hpp>
+#include <com/sun/star/reflection/theCoreReflection.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Type.hxx>
+#include <com/sun/star/uno/TypeClass.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/propertysetmixin.hxx>
+#include <cppuhelper/weak.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+#include <salhelper/simplereferenceobject.hxx>
+
+using cppu::PropertySetMixinImpl;
+
+namespace {
+
+struct PropertyData {
+ explicit PropertyData(
+ css::beans::Property theProperty, bool thePresent):
+ property(std::move(theProperty)), present(thePresent) {}
+
+ css::beans::Property property;
+ bool present;
+};
+
+struct Data: public salhelper::SimpleReferenceObject {
+ typedef std::map< OUString, PropertyData > PropertyMap;
+
+ PropertyMap properties;
+
+ PropertyMap::const_iterator get(
+ css::uno::Reference< css::uno::XInterface > const & object,
+ OUString const & name) const;
+
+protected:
+ void initProperties(
+ css::uno::Reference< css::reflection::XTypeDescription > const & type,
+ css::uno::Sequence< OUString > const & absentOptional,
+ std::vector< OUString > * handleNames)
+ {
+ std::set<OUString> seen;
+ initProperties(type, absentOptional, handleNames, &seen);
+ }
+
+private:
+ void initProperties(
+ css::uno::Reference< css::reflection::XTypeDescription > const & type,
+ css::uno::Sequence< OUString > const & absentOptional,
+ std::vector< OUString > * handleNames, std::set<OUString> * seen);
+
+ static css::uno::Reference< css::reflection::XTypeDescription >
+ resolveTypedefs(
+ css::uno::Reference< css::reflection::XTypeDescription > const & type);
+};
+
+Data::PropertyMap::const_iterator Data::get(
+ css::uno::Reference< css::uno::XInterface > const & object,
+ OUString const & name) const
+{
+ PropertyMap::const_iterator i(properties.find(name));
+ if (i == properties.end() || !i->second.present) {
+ throw css::beans::UnknownPropertyException(name, object);
+ }
+ return i;
+}
+
+void Data::initProperties(
+ css::uno::Reference< css::reflection::XTypeDescription > const & type,
+ css::uno::Sequence< OUString > const & absentOptional,
+ std::vector< OUString > * handleNames, std::set<OUString> * seen)
+{
+ css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > ifc(
+ resolveTypedefs(type), css::uno::UNO_QUERY_THROW);
+ if (!seen->insert(ifc->getName()).second)
+ return;
+
+ const css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > > bases(
+ ifc->getBaseTypes());
+ for (const auto & i : bases) {
+ initProperties(i, absentOptional, handleNames, seen);
+ }
+ const css::uno::Sequence<
+ css::uno::Reference<
+ css::reflection::XInterfaceMemberTypeDescription > > members(
+ ifc->getMembers());
+ OUString const * absentBegin = absentOptional.getConstArray();
+ OUString const * absentEnd =
+ absentBegin + absentOptional.getLength();
+ for (const auto & m : members) {
+ if (m->getTypeClass()
+ == css::uno::TypeClass_INTERFACE_ATTRIBUTE)
+ {
+ css::uno::Reference<
+ css::reflection::XInterfaceAttributeTypeDescription2 > attr(
+ m, css::uno::UNO_QUERY_THROW);
+ sal_Int16 attrAttribs = 0;
+ if (attr->isBound()) {
+ attrAttribs |= css::beans::PropertyAttribute::BOUND;
+ }
+ bool bSetUnknown = false;
+ if (attr->isReadOnly()) {
+ attrAttribs |= css::beans::PropertyAttribute::READONLY;
+ bSetUnknown = true;
+ }
+ css::uno::Sequence<
+ css::uno::Reference<
+ css::reflection::XCompoundTypeDescription > > excs(
+ attr->getGetExceptions());
+ bool bGetUnknown = false;
+ //XXX Special interpretation of getter/setter exceptions only
+ // works if the specified exceptions are of the exact type, not
+ // of a supertype:
+ for (const auto & ex : std::as_const(excs)) {
+ if ( ex->getName() == "com.sun.star.beans.UnknownPropertyException" )
+ {
+ bGetUnknown = true;
+ break;
+ }
+ }
+ excs = attr->getSetExceptions();
+ for (const auto & ex : std::as_const(excs)) {
+ if ( ex->getName() == "com.sun.star.beans.UnknownPropertyException" )
+ {
+ bSetUnknown = true;
+ } else if ( ex->getName() == "com.sun.star.beans.PropertyVetoException" )
+ {
+ attrAttribs
+ |= css::beans::PropertyAttribute::CONSTRAINED;
+ }
+ }
+ if (bGetUnknown && bSetUnknown) {
+ attrAttribs |= css::beans::PropertyAttribute::OPTIONAL;
+ }
+ css::uno::Reference< css::reflection::XTypeDescription > t(
+ attr->getType());
+ for (;;)
+ {
+ t = resolveTypedefs(t);
+ sal_Int16 n;
+ if (t->getName().startsWith(
+ "com.sun.star.beans.Ambiguous<"))
+ {
+ n = css::beans::PropertyAttribute::MAYBEAMBIGUOUS;
+ } else if (t->getName().startsWith(
+ "com.sun.star.beans.Defaulted<"))
+ {
+ n = css::beans::PropertyAttribute::MAYBEDEFAULT;
+ } else if (t->getName().startsWith(
+ "com.sun.star.beans.Optional<"))
+ {
+ n = css::beans::PropertyAttribute::MAYBEVOID;
+ } else {
+ break;
+ }
+ if ((attrAttribs & n) != 0) {
+ break;
+ }
+ attrAttribs |= n;
+ const css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > >
+ args(
+ css::uno::Reference<
+ css::reflection::XStructTypeDescription >(
+ t, css::uno::UNO_QUERY_THROW)->
+ getTypeArguments());
+ if (args.getLength() != 1) {
+ throw css::uno::RuntimeException(
+ "inconsistent UNO type registry");
+ }
+ t = args[0];
+ }
+ std::vector< OUString >::size_type handles
+ = handleNames->size();
+ if (handles > SAL_MAX_INT32) {
+ throw css::uno::RuntimeException(
+ "interface type has too many attributes");
+ }
+ OUString name(m->getMemberName());
+ if (!properties.emplace(
+ name,
+ PropertyData(
+ css::beans::Property(
+ name, static_cast< sal_Int32 >(handles),
+ css::uno::Type(
+ t->getTypeClass(), t->getName()),
+ attrAttribs),
+ (std::find(absentBegin, absentEnd, name)
+ == absentEnd))).
+ second)
+ {
+ throw css::uno::RuntimeException(
+ "inconsistent UNO type registry");
+ }
+ handleNames->push_back(name);
+ }
+ }
+}
+
+css::uno::Reference< css::reflection::XTypeDescription > Data::resolveTypedefs(
+ css::uno::Reference< css::reflection::XTypeDescription > const & type)
+{
+ css::uno::Reference< css::reflection::XTypeDescription > t(type);
+ while (t->getTypeClass() == css::uno::TypeClass_TYPEDEF) {
+ t = css::uno::Reference< css::reflection::XIndirectTypeDescription >(
+ t, css::uno::UNO_QUERY_THROW)->getReferencedType();
+ }
+ return t;
+}
+
+class Info: public cppu::WeakImplHelper< css::beans::XPropertySetInfo > {
+public:
+ explicit Info(Data * data): m_data(data) {}
+
+ virtual css::uno::Sequence< css::beans::Property > SAL_CALL getProperties() override;
+
+ virtual css::beans::Property SAL_CALL getPropertyByName(
+ OUString const & name) override;
+
+ virtual sal_Bool SAL_CALL hasPropertyByName(OUString const & name) override;
+
+private:
+ rtl::Reference< Data > m_data;
+};
+
+css::uno::Sequence< css::beans::Property > Info::getProperties()
+{
+ assert(m_data->properties.size() <= SAL_MAX_INT32);
+ css::uno::Sequence< css::beans::Property > s(
+ static_cast< sal_Int32 >(m_data->properties.size()));
+ auto r = asNonConstRange(s);
+ sal_Int32 n = 0;
+ for (const auto& rEntry : m_data->properties)
+ {
+ if (rEntry.second.present) {
+ r[n++] = rEntry.second.property;
+ }
+ }
+ s.realloc(n);
+ return s;
+}
+
+css::beans::Property Info::getPropertyByName(OUString const & name)
+{
+ return m_data->get(static_cast< cppu::OWeakObject * >(this), name)->
+ second.property;
+}
+
+sal_Bool Info::hasPropertyByName(OUString const & name)
+{
+ Data::PropertyMap::iterator i(m_data->properties.find(name));
+ return i != m_data->properties.end() && i->second.present;
+}
+
+typedef
+std::multiset< css::uno::Reference< css::beans::XPropertyChangeListener > >
+BoundListenerBag;
+
+}
+
+class PropertySetMixinImpl::BoundListeners::Impl {
+public:
+ BoundListenerBag specificListeners;
+ BoundListenerBag unspecificListeners;
+ css::beans::PropertyChangeEvent event;
+};
+
+PropertySetMixinImpl::BoundListeners::BoundListeners(): m_impl(new Impl) {}
+
+PropertySetMixinImpl::BoundListeners::~BoundListeners() {
+ delete m_impl;
+}
+
+void PropertySetMixinImpl::BoundListeners::notify() const {
+ for (const auto& rxListener : m_impl->specificListeners)
+ {
+ try {
+ rxListener->propertyChange(m_impl->event);
+ } catch (css::lang::DisposedException &) {}
+ }
+ for (const auto& rxListener : m_impl->unspecificListeners)
+ {
+ try {
+ rxListener->propertyChange(m_impl->event);
+ } catch (css::lang::DisposedException &) {}
+ }
+}
+
+class PropertySetMixinImpl::Impl: public Data {
+public:
+ Impl(
+ css::uno::Reference< css::uno::XComponentContext > const & context,
+ Implements theImplements,
+ css::uno::Sequence< OUString > const & absentOptional,
+ css::uno::Type const & type);
+
+ OUString const & translateHandle(
+ css::uno::Reference< css::uno::XInterface > const & object,
+ sal_Int32 handle) const;
+
+ void setProperty(
+ css::uno::Reference< css::uno::XInterface > const & object,
+ OUString const & name, css::uno::Any const & value,
+ bool isAmbiguous, bool isDefaulted, sal_Int16 illegalArgumentPosition)
+ const;
+
+ css::uno::Any getProperty(
+ css::uno::Reference< css::uno::XInterface > const & object,
+ OUString const & name, css::beans::PropertyState * state) const;
+
+ PropertySetMixinImpl::Implements implements;
+ css::uno::Sequence< OUString > handleMap;
+
+ typedef std::map< OUString, BoundListenerBag > BoundListenerMap;
+
+ typedef
+ std::multiset< css::uno::Reference< css::beans::XVetoableChangeListener > >
+ VetoListenerBag;
+
+ typedef std::map< OUString, VetoListenerBag > VetoListenerMap;
+
+ mutable std::mutex mutex;
+ BoundListenerMap boundListeners;
+ VetoListenerMap vetoListeners;
+ bool disposed;
+
+private:
+ css::uno::Reference< css::reflection::XIdlClass > getReflection(
+ OUString const & typeName) const;
+
+ static css::uno::Any wrapValue(
+ css::uno::Reference< css::uno::XInterface > const & object,
+ css::uno::Any const & value,
+ css::uno::Reference< css::reflection::XIdlClass > const & type,
+ bool wrapAmbiguous, bool isAmbiguous, bool wrapDefaulted,
+ bool isDefaulted, bool wrapOptional);
+
+ css::uno::Reference< css::uno::XComponentContext > const & m_context;
+ css::uno::Type m_type;
+ css::uno::Reference< css::reflection::XIdlClass > m_idlClass;
+};
+
+PropertySetMixinImpl::Impl::Impl(
+ css::uno::Reference< css::uno::XComponentContext > const & context,
+ Implements theImplements,
+ css::uno::Sequence< OUString > const & absentOptional,
+ css::uno::Type const & type):
+ implements(theImplements), disposed(false), m_context(context),
+ m_type(type)
+{
+ assert(context.is());
+ assert(
+ (implements
+ & ~(IMPLEMENTS_PROPERTY_SET | IMPLEMENTS_FAST_PROPERTY_SET
+ | IMPLEMENTS_PROPERTY_ACCESS))
+ == 0);
+ m_idlClass = getReflection(m_type.getTypeName());
+ css::uno::Reference< css::reflection::XTypeDescription > ifc;
+ try {
+ ifc.set(
+ css::uno::Reference< css::container::XHierarchicalNameAccess >(
+ m_context->getValueByName(
+ "/singletons/com.sun.star.reflection."
+ "theTypeDescriptionManager"),
+ css::uno::UNO_QUERY_THROW)->getByHierarchicalName(
+ m_type.getTypeName()),
+ css::uno::UNO_QUERY_THROW);
+ } catch (css::container::NoSuchElementException & e) {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException(
+ "unexpected com.sun.star.container.NoSuchElementException: "
+ + e.Message,
+ nullptr, anyEx );
+ }
+ std::vector< OUString > handleNames;
+ initProperties(ifc, absentOptional, &handleNames);
+ std::vector< OUString >::size_type size = handleNames.size();
+ assert(size <= SAL_MAX_INT32);
+ handleMap.realloc(static_cast< sal_Int32 >(size));
+ std::copy(handleNames.begin(), handleNames.end(), handleMap.getArray());
+}
+
+OUString const & PropertySetMixinImpl::Impl::translateHandle(
+ css::uno::Reference< css::uno::XInterface > const & object,
+ sal_Int32 handle) const
+{
+ if (handle < 0 || handle >= handleMap.getLength()) {
+ throw css::beans::UnknownPropertyException(
+ "bad handle " + OUString::number(handle), object);
+ }
+ return handleMap[handle];
+}
+
+void PropertySetMixinImpl::Impl::setProperty(
+ css::uno::Reference< css::uno::XInterface > const & object,
+ OUString const & name, css::uno::Any const & value, bool isAmbiguous,
+ bool isDefaulted, sal_Int16 illegalArgumentPosition) const
+{
+ PropertyMap::const_iterator i(properties.find(name));
+ if (i == properties.end()) {
+ throw css::beans::UnknownPropertyException(name, object);
+ }
+ if ((isAmbiguous
+ && ((i->second.property.Attributes
+ & css::beans::PropertyAttribute::MAYBEAMBIGUOUS)
+ == 0))
+ || (isDefaulted
+ && ((i->second.property.Attributes
+ & css::beans::PropertyAttribute::MAYBEDEFAULT)
+ == 0)))
+ {
+ throw css::lang::IllegalArgumentException(
+ ("flagging as ambiguous/defaulted non-ambiguous/defaulted property "
+ + name),
+ object, illegalArgumentPosition);
+ }
+ css::uno::Reference< css::reflection::XIdlField2 > f(
+ m_idlClass->getField(name), css::uno::UNO_QUERY_THROW);
+ css::uno::Any o(object->queryInterface(m_type));
+ css::uno::Any v(
+ wrapValue(
+ object, value,
+ (css::uno::Reference< css::reflection::XIdlField2 >(
+ m_idlClass->getField(name), css::uno::UNO_QUERY_THROW)->
+ getType()),
+ ((i->second.property.Attributes
+ & css::beans::PropertyAttribute::MAYBEAMBIGUOUS)
+ != 0),
+ isAmbiguous,
+ ((i->second.property.Attributes
+ & css::beans::PropertyAttribute::MAYBEDEFAULT)
+ != 0),
+ isDefaulted,
+ ((i->second.property.Attributes
+ & css::beans::PropertyAttribute::MAYBEVOID)
+ != 0)));
+ try {
+ f->set(o, v);
+ } catch (css::lang::IllegalArgumentException & e) {
+ if (e.ArgumentPosition == 1) {
+ throw css::lang::IllegalArgumentException(
+ e.Message, object, illegalArgumentPosition);
+ } else {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException(
+ "unexpected com.sun.star.lang.IllegalArgumentException: "
+ + e.Message,
+ object, anyEx );
+ }
+ } catch (css::lang::IllegalAccessException &) {
+ //TODO Clarify whether PropertyVetoException is the correct exception
+ // to throw when trying to set a read-only property:
+ throw css::beans::PropertyVetoException(
+ "cannot set read-only property " + name, object);
+ } catch (css::lang::WrappedTargetRuntimeException & e) {
+ //FIXME A WrappedTargetRuntimeException from XIdlField2.get is not
+ // guaranteed to originate directly within XIdlField2.get (and thus have
+ // the expected semantics); it might also be passed through from lower
+ // layers.
+ if (e.TargetException.isExtractableTo(
+ cppu::UnoType<css::beans::UnknownPropertyException>::get())
+ && ((i->second.property.Attributes
+ & css::beans::PropertyAttribute::OPTIONAL)
+ != 0))
+ {
+ throw css::beans::UnknownPropertyException(name, object);
+ } else if (e.TargetException.isExtractableTo(
+ cppu::UnoType<css::beans::PropertyVetoException>::get())
+ && ((i->second.property.Attributes
+ & css::beans::PropertyAttribute::CONSTRAINED)
+ != 0))
+ {
+ css::beans::PropertyVetoException exc;
+ e.TargetException >>= exc;
+ if (exc.Message.isEmpty() )
+ throw css::beans::PropertyVetoException("Invalid " + name, object);
+ else
+ throw exc;
+ } else {
+ throw css::lang::WrappedTargetException(
+ e.Message, object, e.TargetException);
+ }
+ }
+}
+
+css::uno::Any PropertySetMixinImpl::Impl::getProperty(
+ css::uno::Reference< css::uno::XInterface > const & object,
+ OUString const & name, css::beans::PropertyState * state) const
+{
+ PropertyMap::const_iterator i(properties.find(name));
+ if (i == properties.end()) {
+ throw css::beans::UnknownPropertyException(name, object);
+ }
+ css::uno::Reference< css::reflection::XIdlField2 > field(
+ m_idlClass->getField(name), css::uno::UNO_QUERY_THROW);
+ css::uno::Any value;
+ try {
+ value = field->get(object->queryInterface(m_type));
+ } catch (css::lang::IllegalArgumentException & e) {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException(
+ "unexpected com.sun.star.lang.IllegalArgumentException: "
+ + e.Message,
+ object, anyEx );
+ } catch (css::lang::WrappedTargetRuntimeException & e) {
+ //FIXME A WrappedTargetRuntimeException from XIdlField2.get is not
+ // guaranteed to originate directly within XIdlField2.get (and thus have
+ // the expected semantics); it might also be passed through from lower
+ // layers.
+ if (e.TargetException.isExtractableTo(
+ cppu::UnoType<css::beans::UnknownPropertyException>::get())
+ && ((i->second.property.Attributes
+ & css::beans::PropertyAttribute::OPTIONAL)
+ != 0))
+ {
+ throw css::beans::UnknownPropertyException(name, object);
+ } else {
+ throw css::lang::WrappedTargetException(
+ e.Message, object, e.TargetException);
+ }
+ }
+ bool undoAmbiguous
+ = ((i->second.property.Attributes
+ & css::beans::PropertyAttribute::MAYBEAMBIGUOUS)
+ != 0);
+ bool undoDefaulted
+ = ((i->second.property.Attributes
+ & css::beans::PropertyAttribute::MAYBEDEFAULT)
+ != 0);
+ bool undoOptional
+ = ((i->second.property.Attributes
+ & css::beans::PropertyAttribute::MAYBEVOID)
+ != 0);
+ bool isAmbiguous = false;
+ bool isDefaulted = false;
+ while (undoAmbiguous || undoDefaulted || undoOptional) {
+ if (undoAmbiguous
+ && value.getValueTypeName().startsWith(
+ "com.sun.star.beans.Ambiguous<"))
+ {
+ css::uno::Reference< css::reflection::XIdlClass > ambiguous(
+ getReflection(value.getValueTypeName()));
+ try {
+ if (!(css::uno::Reference< css::reflection::XIdlField2 >(
+ ambiguous->getField("IsAmbiguous"),
+ css::uno::UNO_QUERY_THROW)->get(value)
+ >>= isAmbiguous))
+ {
+ throw css::uno::RuntimeException(
+ ("unexpected type of com.sun.star.beans.Ambiguous"
+ " IsAmbiguous member"),
+ object);
+ }
+ value = css::uno::Reference< css::reflection::XIdlField2 >(
+ ambiguous->getField("Value"), css::uno::UNO_QUERY_THROW)->
+ get(value);
+ } catch (css::lang::IllegalArgumentException & e) {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException(
+ "unexpected com.sun.star.lang.IllegalArgumentException: "
+ + e.Message,
+ object, anyEx );
+ }
+ undoAmbiguous = false;
+ } else if (undoDefaulted
+ && value.getValueTypeName().startsWith(
+ "com.sun.star.beans.Defaulted<"))
+ {
+ css::uno::Reference< css::reflection::XIdlClass > defaulted(
+ getReflection(value.getValueTypeName()));
+ try {
+
+ if (!(css::uno::Reference< css::reflection::XIdlField2 >(
+ defaulted->getField("IsDefaulted"),
+ css::uno::UNO_QUERY_THROW)->get(value)
+ >>= isDefaulted))
+ {
+ throw css::uno::RuntimeException(
+ ("unexpected type of com.sun.star.beans.Defaulted"
+ " IsDefaulted member"),
+ object);
+ }
+ value = css::uno::Reference< css::reflection::XIdlField2 >(
+ defaulted->getField("Value"), css::uno::UNO_QUERY_THROW)->
+ get(value);
+ } catch (css::lang::IllegalArgumentException & e) {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException(
+ "unexpected com.sun.star.lang.IllegalArgumentException: "
+ + e.Message,
+ object, anyEx );
+ }
+ undoDefaulted = false;
+ } else if (undoOptional
+ && value.getValueTypeName().startsWith(
+ "com.sun.star.beans.Optional<"))
+ {
+ css::uno::Reference< css::reflection::XIdlClass > optional(
+ getReflection(value.getValueTypeName()));
+ try {
+ bool present = false;
+ if (!(css::uno::Reference< css::reflection::XIdlField2 >(
+ optional->getField("IsPresent"),
+ css::uno::UNO_QUERY_THROW)->get(value)
+ >>= present))
+ {
+ throw css::uno::RuntimeException(
+ ("unexpected type of com.sun.star.beans.Optional"
+ " IsPresent member"),
+ object);
+ }
+ if (!present) {
+ value.clear();
+ break;
+ }
+ value = css::uno::Reference< css::reflection::XIdlField2 >(
+ optional->getField("Value"), css::uno::UNO_QUERY_THROW)->
+ get(value);
+ } catch (css::lang::IllegalArgumentException & e) {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException(
+ "unexpected com.sun.star.lang.IllegalArgumentException: "
+ + e.Message,
+ object, anyEx );
+ }
+ undoOptional = false;
+ } else {
+ throw css::uno::RuntimeException(
+ "unexpected type of attribute " + name, object);
+ }
+ }
+ if (state != nullptr) {
+ //XXX If isAmbiguous && isDefaulted, arbitrarily choose AMBIGUOUS_VALUE
+ // over DEFAULT_VALUE:
+ *state = isAmbiguous
+ ? css::beans::PropertyState_AMBIGUOUS_VALUE
+ : isDefaulted
+ ? css::beans::PropertyState_DEFAULT_VALUE
+ : css::beans::PropertyState_DIRECT_VALUE;
+ }
+ return value;
+}
+
+css::uno::Reference< css::reflection::XIdlClass >
+PropertySetMixinImpl::Impl::getReflection(OUString const & typeName) const
+{
+ return css::uno::Reference< css::reflection::XIdlClass >(
+ css::reflection::theCoreReflection::get(m_context)->forName(typeName),
+ css::uno::UNO_SET_THROW);
+}
+
+css::uno::Any PropertySetMixinImpl::Impl::wrapValue(
+ css::uno::Reference< css::uno::XInterface > const & object,
+ css::uno::Any const & value,
+ css::uno::Reference< css::reflection::XIdlClass > const & type,
+ bool wrapAmbiguous, bool isAmbiguous, bool wrapDefaulted, bool isDefaulted,
+ bool wrapOptional)
+{
+ assert(wrapAmbiguous || !isAmbiguous);
+ assert(wrapDefaulted || !isDefaulted);
+ if (wrapAmbiguous
+ && type->getName().startsWith("com.sun.star.beans.Ambiguous<"))
+ {
+ css::uno::Any strct;
+ type->createObject(strct);
+ try {
+ css::uno::Reference< css::reflection::XIdlField2 > field(
+ type->getField("Value"), css::uno::UNO_QUERY_THROW);
+ field->set(
+ strct,
+ wrapValue(
+ object, value, field->getType(), false, false,
+ wrapDefaulted, isDefaulted, wrapOptional));
+ css::uno::Reference< css::reflection::XIdlField2 >(
+ type->getField("IsAmbiguous"), css::uno::UNO_QUERY_THROW)->set(
+ strct, css::uno::Any(isAmbiguous));
+ } catch (css::lang::IllegalArgumentException & e) {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException(
+ "unexpected com.sun.star.lang.IllegalArgumentException: "
+ + e.Message,
+ object, anyEx );
+ } catch (css::lang::IllegalAccessException & e) {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException(
+ "unexpected com.sun.star.lang.IllegalAccessException: "
+ + e.Message,
+ object, anyEx );
+ }
+ return strct;
+ }
+ if (wrapDefaulted
+ && type->getName().startsWith("com.sun.star.beans.Defaulted<"))
+ {
+ css::uno::Any strct;
+ type->createObject(strct);
+ try {
+ css::uno::Reference< css::reflection::XIdlField2 > field(
+ type->getField("Value"), css::uno::UNO_QUERY_THROW);
+ field->set(
+ strct,
+ wrapValue(
+ object, value, field->getType(), wrapAmbiguous, isAmbiguous,
+ false, false, wrapOptional));
+ css::uno::Reference< css::reflection::XIdlField2 >(
+ type->getField("IsDefaulted"), css::uno::UNO_QUERY_THROW)->set(
+ strct, css::uno::Any(isDefaulted));
+ } catch (css::lang::IllegalArgumentException & e) {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException(
+ "unexpected com.sun.star.lang.IllegalArgumentException: "
+ + e.Message,
+ object, anyEx );
+ } catch (css::lang::IllegalAccessException & e) {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException(
+ "unexpected com.sun.star.lang.IllegalAccessException: "
+ + e.Message,
+ object, anyEx );
+ }
+ return strct;
+ }
+ if (wrapOptional
+ && type->getName().startsWith("com.sun.star.beans.Optional<"))
+ {
+ css::uno::Any strct;
+ type->createObject(strct);
+ bool present = value.hasValue();
+ try {
+ css::uno::Reference< css::reflection::XIdlField2 >(
+ type->getField("IsPresent"), css::uno::UNO_QUERY_THROW)->set(
+ strct, css::uno::Any(present));
+ if (present) {
+ css::uno::Reference< css::reflection::XIdlField2 > field(
+ type->getField("Value"), css::uno::UNO_QUERY_THROW);
+ field->set(
+ strct,
+ wrapValue(
+ object, value, field->getType(), wrapAmbiguous,
+ isAmbiguous, wrapDefaulted, isDefaulted, false));
+ }
+ } catch (css::lang::IllegalArgumentException & e) {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException(
+ "unexpected com.sun.star.lang.IllegalArgumentException: "
+ + e.Message,
+ object, anyEx );
+ } catch (css::lang::IllegalAccessException & e) {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException(
+ "unexpected com.sun.star.lang.IllegalAccessException: "
+ + e.Message,
+ object, anyEx );
+ }
+ return strct;
+ }
+ if (wrapAmbiguous || wrapDefaulted || wrapOptional) {
+ throw css::uno::RuntimeException(
+ "unexpected type of attribute", object);
+ }
+ return value;
+}
+
+PropertySetMixinImpl::PropertySetMixinImpl(
+ css::uno::Reference< css::uno::XComponentContext > const & context,
+ Implements implements,
+ css::uno::Sequence< OUString > const & absentOptional,
+ css::uno::Type const & type)
+{
+ m_impl = new Impl(context, implements, absentOptional, type);
+ m_impl->acquire();
+}
+
+PropertySetMixinImpl::~PropertySetMixinImpl() {
+ m_impl->release();
+}
+
+void PropertySetMixinImpl::checkUnknown(OUString const & propertyName) {
+ if (!propertyName.isEmpty()) {
+ m_impl->get(
+ static_cast< css::beans::XPropertySet * >(this), propertyName);
+ }
+}
+
+void PropertySetMixinImpl::prepareSet(
+ OUString const & propertyName, css::uno::Any const & oldValue,
+ css::uno::Any const & newValue, BoundListeners * boundListeners)
+{
+ Impl::PropertyMap::const_iterator it(m_impl->properties.find(propertyName));
+ assert(it != m_impl->properties.end());
+ Impl::VetoListenerBag specificVeto;
+ Impl::VetoListenerBag unspecificVeto;
+ {
+ std::scoped_lock g(m_impl->mutex);
+ if (m_impl->disposed) {
+ throw css::lang::DisposedException(
+ "disposed", static_cast< css::beans::XPropertySet * >(this));
+ }
+ if ((it->second.property.Attributes
+ & css::beans::PropertyAttribute::CONSTRAINED)
+ != 0)
+ {
+ Impl::VetoListenerMap::const_iterator i(
+ m_impl->vetoListeners.find(propertyName));
+ if (i != m_impl->vetoListeners.end()) {
+ specificVeto = i->second;
+ }
+ i = m_impl->vetoListeners.find("");
+ if (i != m_impl->vetoListeners.end()) {
+ unspecificVeto = i->second;
+ }
+ }
+ if ((it->second.property.Attributes
+ & css::beans::PropertyAttribute::BOUND)
+ != 0)
+ {
+ assert(boundListeners != nullptr);
+ Impl::BoundListenerMap::const_iterator i(
+ m_impl->boundListeners.find(propertyName));
+ if (i != m_impl->boundListeners.end()) {
+ boundListeners->m_impl->specificListeners = i->second;
+ }
+ i = m_impl->boundListeners.find("");
+ if (i != m_impl->boundListeners.end()) {
+ boundListeners->m_impl->unspecificListeners = i->second;
+ }
+ }
+ }
+ if ((it->second.property.Attributes
+ & css::beans::PropertyAttribute::CONSTRAINED)
+ != 0)
+ {
+ css::beans::PropertyChangeEvent event(
+ static_cast< css::beans::XPropertySet * >(this), propertyName,
+ false, it->second.property.Handle, oldValue, newValue);
+ for (auto& rxVetoListener : specificVeto)
+ {
+ try {
+ rxVetoListener->vetoableChange(event);
+ } catch (css::lang::DisposedException &) {}
+ }
+ for (auto& rxVetoListener : unspecificVeto)
+ {
+ try {
+ rxVetoListener->vetoableChange(event);
+ } catch (css::lang::DisposedException &) {}
+ }
+ }
+ if ((it->second.property.Attributes & css::beans::PropertyAttribute::BOUND)
+ != 0)
+ {
+ assert(boundListeners != nullptr);
+ boundListeners->m_impl->event = css::beans::PropertyChangeEvent(
+ static_cast< css::beans::XPropertySet * >(this), propertyName,
+ false, it->second.property.Handle, oldValue, newValue);
+ }
+}
+
+void PropertySetMixinImpl::dispose() {
+ Impl::BoundListenerMap boundListeners;
+ Impl::VetoListenerMap vetoListeners;
+ {
+ std::scoped_lock g(m_impl->mutex);
+ boundListeners.swap(m_impl->boundListeners);
+ vetoListeners.swap(m_impl->vetoListeners);
+ m_impl->disposed = true;
+ }
+ css::lang::EventObject event(
+ static_cast< css::beans::XPropertySet * >(this));
+ for (const auto& rEntry : boundListeners)
+ {
+ for (auto& rxBoundListener : rEntry.second)
+ {
+ rxBoundListener->disposing(event);
+ }
+ }
+ for (const auto& rEntry : vetoListeners)
+ {
+ for (auto& rxVetoListener : rEntry.second)
+ {
+ rxVetoListener->disposing(event);
+ }
+ }
+}
+
+css::uno::Any PropertySetMixinImpl::queryInterface(css::uno::Type const & type)
+{
+ if ((m_impl->implements & IMPLEMENTS_PROPERTY_SET) != 0
+ && type == css::beans::XPropertySet::static_type())
+ {
+ css::uno::Reference< css::uno::XInterface > ifc(
+ static_cast< css::beans::XPropertySet * >(this));
+ return css::uno::Any(&ifc, type);
+ }
+ if ((m_impl->implements & IMPLEMENTS_FAST_PROPERTY_SET) != 0
+ && type == css::beans::XFastPropertySet::static_type())
+ {
+ css::uno::Reference< css::uno::XInterface > ifc(
+ static_cast< css::beans::XFastPropertySet * >(this));
+ return css::uno::Any(&ifc, type);
+ }
+ if ((m_impl->implements & IMPLEMENTS_PROPERTY_ACCESS) != 0
+ && type == css::beans::XPropertyAccess::static_type())
+ {
+ css::uno::Reference< css::uno::XInterface > ifc(
+ static_cast< css::beans::XPropertyAccess * >(this));
+ return css::uno::Any(&ifc, type);
+ }
+ return css::uno::Any();
+}
+
+css::uno::Reference< css::beans::XPropertySetInfo >
+PropertySetMixinImpl::getPropertySetInfo()
+{
+ return new Info(m_impl);
+}
+
+void PropertySetMixinImpl::setPropertyValue(
+ OUString const & propertyName, css::uno::Any const & value)
+{
+ m_impl->setProperty(
+ static_cast< css::beans::XPropertySet * >(this), propertyName, value,
+ false, false, 1);
+}
+
+css::uno::Any PropertySetMixinImpl::getPropertyValue(
+ OUString const & propertyName)
+{
+ return m_impl->getProperty(
+ static_cast< css::beans::XPropertySet * >(this), propertyName, nullptr);
+}
+
+void PropertySetMixinImpl::addPropertyChangeListener(
+ OUString const & propertyName,
+ css::uno::Reference< css::beans::XPropertyChangeListener > const & listener)
+{
+ css::uno::Reference< css::beans::XPropertyChangeListener >(
+ listener, css::uno::UNO_SET_THROW); // reject NULL listener
+ checkUnknown(propertyName);
+ bool disposed;
+ {
+ std::scoped_lock g(m_impl->mutex);
+ disposed = m_impl->disposed;
+ if (!disposed) {
+ m_impl->boundListeners[propertyName].insert(listener);
+ }
+ }
+ if (disposed) {
+ listener->disposing(
+ css::lang::EventObject(
+ static_cast< css::beans::XPropertySet * >(this)));
+ }
+}
+
+void PropertySetMixinImpl::removePropertyChangeListener(
+ OUString const & propertyName,
+ css::uno::Reference< css::beans::XPropertyChangeListener > const & listener)
+{
+ assert(listener.is());
+ checkUnknown(propertyName);
+ std::scoped_lock g(m_impl->mutex);
+ Impl::BoundListenerMap::iterator i(
+ m_impl->boundListeners.find(propertyName));
+ if (i != m_impl->boundListeners.end()) {
+ BoundListenerBag::iterator j(i->second.find(listener));
+ if (j != i->second.end()) {
+ i->second.erase(j);
+ }
+ }
+}
+
+void PropertySetMixinImpl::addVetoableChangeListener(
+ OUString const & propertyName,
+ css::uno::Reference< css::beans::XVetoableChangeListener > const & listener)
+{
+ css::uno::Reference< css::beans::XVetoableChangeListener >(
+ listener, css::uno::UNO_SET_THROW); // reject NULL listener
+ checkUnknown(propertyName);
+ bool disposed;
+ {
+ std::scoped_lock g(m_impl->mutex);
+ disposed = m_impl->disposed;
+ if (!disposed) {
+ m_impl->vetoListeners[propertyName].insert(listener);
+ }
+ }
+ if (disposed) {
+ listener->disposing(
+ css::lang::EventObject(
+ static_cast< css::beans::XPropertySet * >(this)));
+ }
+}
+
+void PropertySetMixinImpl::removeVetoableChangeListener(
+ OUString const & propertyName,
+ css::uno::Reference< css::beans::XVetoableChangeListener > const & listener)
+{
+ assert(listener.is());
+ checkUnknown(propertyName);
+ std::scoped_lock g(m_impl->mutex);
+ Impl::VetoListenerMap::iterator i(m_impl->vetoListeners.find(propertyName));
+ if (i != m_impl->vetoListeners.end()) {
+ Impl::VetoListenerBag::iterator j(i->second.find(listener));
+ if (j != i->second.end()) {
+ i->second.erase(j);
+ }
+ }
+}
+
+void PropertySetMixinImpl::setFastPropertyValue(
+ sal_Int32 handle, css::uno::Any const & value)
+{
+ m_impl->setProperty(
+ static_cast< css::beans::XPropertySet * >(this),
+ m_impl->translateHandle(
+ static_cast< css::beans::XPropertySet * >(this), handle),
+ value, false, false, 1);
+}
+
+css::uno::Any PropertySetMixinImpl::getFastPropertyValue(sal_Int32 handle)
+{
+ return m_impl->getProperty(
+ static_cast< css::beans::XPropertySet * >(this),
+ m_impl->translateHandle(
+ static_cast< css::beans::XPropertySet * >(this), handle),
+ nullptr);
+}
+
+css::uno::Sequence< css::beans::PropertyValue >
+PropertySetMixinImpl::getPropertyValues()
+{
+ css::uno::Sequence< css::beans::PropertyValue > s(
+ m_impl->handleMap.getLength());
+ auto r = asNonConstRange(s);
+ sal_Int32 n = 0;
+ for (sal_Int32 i = 0; i < m_impl->handleMap.getLength(); ++i) {
+ try {
+ r[n].Value = m_impl->getProperty(
+ static_cast< css::beans::XPropertySet * >(this),
+ m_impl->handleMap[i], &r[n].State);
+ } catch (css::beans::UnknownPropertyException &) {
+ continue;
+ } catch (css::lang::WrappedTargetException & e) {
+ throw css::lang::WrappedTargetRuntimeException(
+ e.Message, static_cast< css::beans::XPropertySet * >(this),
+ e.TargetException);
+ }
+ r[n].Name = m_impl->handleMap[i];
+ r[n].Handle = i;
+ ++n;
+ }
+ s.realloc(n);
+ return s;
+}
+
+void PropertySetMixinImpl::setPropertyValues(
+ css::uno::Sequence< css::beans::PropertyValue > const & props)
+{
+ for (const auto & p : props) {
+ if (p.Handle != -1
+ && (p.Name
+ != m_impl->translateHandle(
+ static_cast< css::beans::XPropertySet * >(this),
+ p.Handle)))
+ {
+ throw css::beans::UnknownPropertyException(
+ ("name " + p.Name + " does not match handle "
+ + OUString::number(p.Handle)),
+ static_cast< css::beans::XPropertySet * >(this));
+ }
+ m_impl->setProperty(
+ static_cast< css::beans::XPropertySet * >(this), p.Name,
+ p.Value,
+ p.State == css::beans::PropertyState_AMBIGUOUS_VALUE,
+ p.State == css::beans::PropertyState_DEFAULT_VALUE, 0);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/propshlp.cxx b/cppuhelper/source/propshlp.cxx
new file mode 100644
index 000000000..3af4cda49
--- /dev/null
+++ b/cppuhelper/source/propshlp.cxx
@@ -0,0 +1,1184 @@
+/* -*- 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 <cppuhelper/propshlp.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <memory>
+#include <sal/log.hxx>
+
+using namespace osl;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::lang;
+using namespace cppu;
+
+namespace cppu {
+
+IPropertyArrayHelper::~IPropertyArrayHelper()
+{
+}
+
+static const css::uno::Type & getPropertyTypeIdentifier( )
+{
+ return cppu::UnoType<XPropertyChangeListener>::get();
+}
+static const css::uno::Type & getPropertiesTypeIdentifier()
+{
+ return cppu::UnoType<XPropertiesChangeListener>::get();
+}
+static const css::uno::Type & getVetoableTypeIdentifier()
+{
+ return cppu::UnoType<XVetoableChangeListener>::get();
+}
+
+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;
+ 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;
+ pR = static_cast<Property *>(bsearch( &PropertyName, aInfos.getConstArray(), aInfos.getLength(),
+ sizeof( Property ),
+ compare_OUString_Property_Impl ));
+ return pR != nullptr;
+}
+
+
+
+class OPropertySetHelper::Impl {
+
+public:
+ Impl( bool i_bIgnoreRuntimeExceptionsWhileFiring,
+ IEventNotificationHook *i_pFireEvents
+ )
+ :m_bIgnoreRuntimeExceptionsWhileFiring( i_bIgnoreRuntimeExceptionsWhileFiring )
+ ,m_bFireEvents(true)
+ ,m_pFireEvents( i_pFireEvents )
+ {
+ }
+
+ bool m_bIgnoreRuntimeExceptionsWhileFiring;
+ bool m_bFireEvents;
+ class IEventNotificationHook * const m_pFireEvents;
+
+ std::vector< sal_Int32 > m_handles;
+ std::vector< Any > m_newValues;
+ std::vector< Any > m_oldValues;
+};
+
+
+
+OPropertySetHelper::OPropertySetHelper(
+ OBroadcastHelper & rBHelper_ )
+ : rBHelper( rBHelper_ ),
+ aBoundLC( rBHelper_.rMutex ),
+ aVetoableLC( rBHelper_.rMutex ),
+ m_pReserved( new Impl(false, nullptr) )
+{
+}
+
+OPropertySetHelper::OPropertySetHelper(
+ OBroadcastHelper & rBHelper_, bool bIgnoreRuntimeExceptionsWhileFiring )
+ : rBHelper( rBHelper_ ),
+ aBoundLC( rBHelper_.rMutex ),
+ aVetoableLC( rBHelper_.rMutex ),
+ m_pReserved( new Impl( bIgnoreRuntimeExceptionsWhileFiring, nullptr ) )
+{
+}
+
+OPropertySetHelper::OPropertySetHelper(
+ OBroadcastHelper & rBHelper_, IEventNotificationHook * i_pFireEvents,
+ bool bIgnoreRuntimeExceptionsWhileFiring)
+ : rBHelper( rBHelper_ ),
+ aBoundLC( rBHelper_.rMutex ),
+ aVetoableLC( rBHelper_.rMutex ),
+ m_pReserved(
+ new Impl( bIgnoreRuntimeExceptionsWhileFiring, i_pFireEvents) )
+{
+}
+
+OPropertySetHelper2::OPropertySetHelper2(
+ OBroadcastHelper & irBHelper,
+ IEventNotificationHook *i_pFireEvents,
+ bool bIgnoreRuntimeExceptionsWhileFiring)
+ :OPropertySetHelper( irBHelper, i_pFireEvents, bIgnoreRuntimeExceptionsWhileFiring )
+{
+}
+
+/**
+ * You must call disposing before.
+ */
+OPropertySetHelper::~OPropertySetHelper()
+{
+ delete m_pReserved;
+}
+OPropertySetHelper2::~OPropertySetHelper2()
+{
+}
+
+// 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 ) );
+}
+
+Any OPropertySetHelper2::queryInterface( const css::uno::Type & rType )
+{
+ Any cnd(cppu::queryInterface(rType, static_cast< XPropertySetOption * >(this)));
+ if ( cnd.hasValue() )
+ return cnd;
+ return OPropertySetHelper::queryInterface(rType);
+}
+
+/**
+ * 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()
+{
+ // 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( aEvt );
+ aVetoableLC.disposeAndClear( 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 );
+ // call the method of the XFastPropertySet interface
+ setFastPropertyValue( nHandle, rValue );
+}
+
+// XPropertySet
+Any OPropertySetHelper::getPropertyValue(
+ 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
+ return getFastPropertyValue( nHandle );
+}
+
+// XPropertySet
+void OPropertySetHelper::addPropertyChangeListener(
+ const OUString& rPropertyName,
+ const Reference < XPropertyChangeListener > & rxListener )
+{
+ MutexGuard aGuard( rBHelper.rMutex );
+ OSL_ENSURE( !rBHelper.bInDispose, "do not addPropertyChangeListener in the dispose call" );
+ OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" );
+ if( rBHelper.bInDispose || rBHelper.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( nHandle, rxListener );
+ }
+ else
+ // add the change listener to the helper container
+ rBHelper.aLC.addInterface(
+ getPropertyTypeIdentifier( ),
+ rxListener
+ );
+}
+
+
+// XPropertySet
+void OPropertySetHelper::removePropertyChangeListener(
+ const OUString& rPropertyName,
+ const Reference < XPropertyChangeListener >& rxListener )
+{
+ MutexGuard aGuard( rBHelper.rMutex );
+ OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" );
+ // all listeners are automatically released in a dispose call
+ if( rBHelper.bInDispose || rBHelper.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( nHandle, rxListener );
+ }
+ else {
+ // remove the change listener to the helper container
+ rBHelper.aLC.removeInterface(
+ getPropertyTypeIdentifier( ),
+ rxListener
+ );
+ }
+}
+
+// XPropertySet
+void OPropertySetHelper::addVetoableChangeListener(
+ const OUString& rPropertyName,
+ const Reference< XVetoableChangeListener > & rxListener )
+{
+ MutexGuard aGuard( rBHelper.rMutex );
+ OSL_ENSURE( !rBHelper.bInDispose, "do not addVetoableChangeListener in the dispose call" );
+ OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" );
+ if( rBHelper.bInDispose || rBHelper.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( nHandle, rxListener );
+ }
+ else
+ // add the vetoable listener to the helper container
+ rBHelper.aLC.addInterface(
+ getVetoableTypeIdentifier( ),
+ rxListener
+ );
+}
+
+// XPropertySet
+void OPropertySetHelper::removeVetoableChangeListener(
+ const OUString& rPropertyName,
+ const Reference < XVetoableChangeListener > & rxListener )
+{
+ MutexGuard aGuard( rBHelper.rMutex );
+ OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" );
+ // all listeners are automatically released in a dispose call
+ if( rBHelper.bInDispose || rBHelper.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( nHandle, rxListener );
+ }
+ else
+ // add the vetoable listener to the helper container
+ rBHelper.aLC.removeInterface(
+ getVetoableTypeIdentifier( ),
+ rxListener
+ );
+}
+
+void OPropertySetHelper::setDependentFastPropertyValue( sal_Int32 i_handle, const css::uno::Any& i_value )
+{
+ //OSL_PRECOND( rBHelper.rMutex.isAcquired(), "OPropertySetHelper::setDependentFastPropertyValue: to be called with a locked mutex only!" );
+ // there is no such thing as Mutex.isAcquired, sadly ...
+
+ 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( 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( 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_pReserved->m_handles.push_back( i_handle );
+ m_pReserved->m_newValues.push_back( aConverted ); // TODO: setFastPropertyValue notifies the unconverted value here ...?
+ m_pReserved->m_oldValues.push_back( aOld );
+}
+
+// XFastPropertySet
+void OPropertySetHelper::setFastPropertyValue( sal_Int32 nHandle, const Any& rValue )
+{
+ OSL_ENSURE( !rBHelper.bInDispose, "do not setFastPropertyValue in the dispose call" );
+ OSL_ENSURE( !rBHelper.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;
+ {
+ MutexGuard aGuard( rBHelper.rMutex );
+ bChanged = convertFastPropertyValue( aConvertedVal, aOldVal, nHandle, rValue );
+ // release guard to fire events
+ }
+ 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( &nHandle, &rValue, &aOldVal, 1, true );
+ }
+
+ {
+ MutexGuard aGuard( rBHelper.rMutex );
+ try
+ {
+ // set the property to the new value
+ setFastPropertyValue_NoBroadcast( 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;
+ }
+
+ // release guard to fire events
+ }
+ // file a change event, if the value changed
+ impl_fireAll( &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;
+ MutexGuard aGuard( rBHelper.rMutex );
+ getFastPropertyValue( aRet, nHandle );
+ return aRet;
+}
+
+
+void OPropertySetHelper::impl_fireAll( sal_Int32* i_handles, const Any* i_newValues, const Any* i_oldValues, sal_Int32 i_count )
+{
+ ClearableMutexGuard aGuard( rBHelper.rMutex );
+ if ( m_pReserved->m_handles.empty() )
+ {
+ aGuard.clear();
+ fire( i_handles, i_newValues, i_oldValues, i_count, false );
+ return;
+ }
+
+ const size_t additionalEvents = m_pReserved->m_handles.size();
+ OSL_ENSURE( additionalEvents == m_pReserved->m_newValues.size()
+ && additionalEvents == m_pReserved->m_oldValues.size(),
+ "OPropertySetHelper::impl_fireAll: inconsistency!" );
+
+ std::vector< sal_Int32 > allHandles( additionalEvents + i_count );
+ std::copy( m_pReserved->m_handles.begin(), m_pReserved->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_pReserved->m_newValues.begin(), m_pReserved->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_pReserved->m_oldValues.begin(), m_pReserved->m_oldValues.end(), allOldValues.begin() );
+ std::copy( i_oldValues, i_oldValues + i_count, allOldValues.begin() + additionalEvents );
+
+ m_pReserved->m_handles.clear();
+ m_pReserved->m_newValues.clear();
+ m_pReserved->m_oldValues.clear();
+
+ aGuard.clear();
+ fire( allHandles.data(), allNewValues.data(), allOldValues.data(), additionalEvents + i_count, false );
+}
+
+
+void OPropertySetHelper::fire
+(
+ sal_Int32 * pnHandles,
+ const Any * pNewValues,
+ const Any * pOldValues,
+ sal_Int32 nHandles, // This is the Count of the array
+ sal_Bool bVetoable
+)
+{
+ if (! m_pReserved->m_bFireEvents)
+ return;
+
+ if (m_pReserved->m_pFireEvents) {
+ m_pReserved->m_pFireEvents->fireEvents(
+ pnHandles, nHandles, bVetoable,
+ m_pReserved->m_bIgnoreRuntimeExceptionsWhileFiring);
+ }
+
+ // 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_pReserved->m_bIgnoreRuntimeExceptionsWhileFiring;
+
+ // fire the events for all changed properties
+ for( i = 0; i < nChangesLen; i++ )
+ {
+ // get the listener container for the property name
+ OInterfaceContainerHelper * pLC;
+ if( bVetoable ) // fire change Events?
+ pLC = aVetoableLC.getContainer( pEvts[i].PropertyHandle );
+ else
+ pLC = aBoundLC.getContainer( pEvts[i].PropertyHandle );
+ if( pLC )
+ {
+ // Iterate over all listeners and send events
+ OInterfaceIteratorHelper aIt( *pLC);
+ while( aIt.hasMoreElements() )
+ {
+ XInterface * pL = aIt.next();
+ try
+ {
+ try
+ {
+ if( bVetoable ) // fire change Events?
+ {
+ static_cast<XVetoableChangeListener *>(pL)->vetoableChange(
+ pEvts[i] );
+ }
+ else
+ {
+ static_cast<XPropertyChangeListener *>(pL)->propertyChange(
+ pEvts[i] );
+ }
+ }
+ catch (DisposedException & exc)
+ {
+ OSL_ENSURE( exc.Context.is(),
+ "DisposedException without Context!" );
+ if (exc.Context == pL)
+ aIt.remove();
+ else
+ throw;
+ }
+ }
+ catch (RuntimeException & exc)
+ {
+ SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc);
+ if (! bIgnoreRuntimeExceptionsWhileFiring)
+ throw;
+ }
+ }
+ }
+ // broadcast to all listeners with "" property name
+ if( bVetoable ){
+ // fire change Events?
+ pLC = rBHelper.aLC.getContainer(
+ getVetoableTypeIdentifier()
+ );
+ }
+ else {
+ pLC = rBHelper.aLC.getContainer(
+ getPropertyTypeIdentifier( )
+ );
+ }
+ if( pLC )
+ {
+ // Iterate over all listeners and send events.
+ OInterfaceIteratorHelper aIt( *pLC);
+ while( aIt.hasMoreElements() )
+ {
+ XInterface * pL = aIt.next();
+ try
+ {
+ try
+ {
+ if( bVetoable ) // fire change Events?
+ {
+ static_cast<XVetoableChangeListener *>(pL)->vetoableChange(
+ pEvts[i] );
+ }
+ else
+ {
+ static_cast<XPropertyChangeListener *>(pL)->propertyChange(
+ pEvts[i] );
+ }
+ }
+ catch (DisposedException & exc)
+ {
+ OSL_ENSURE( exc.Context.is(),
+ "DisposedException without Context!" );
+ if (exc.Context == pL)
+ aIt.remove();
+ else
+ throw;
+ }
+ }
+ catch (RuntimeException & exc)
+ {
+ SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc);
+ if (! bIgnoreRuntimeExceptionsWhileFiring)
+ throw;
+ }
+ }
+ }
+ }
+
+ // reduce array to changed properties
+ aEvts.realloc( nChangesLen );
+
+ if( bVetoable )
+ return;
+
+ auto pCont = rBHelper.aLC.getContainer(getPropertiesTypeIdentifier());
+ if (!pCont)
+ return;
+
+ // Here is a Bug, unbound properties are also fired
+ OInterfaceIteratorHelper aIt( *pCont );
+ while( aIt.hasMoreElements() )
+ {
+ XPropertiesChangeListener * pL =
+ static_cast<XPropertiesChangeListener *>(aIt.next());
+ 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)
+ aIt.remove();
+ else
+ throw;
+ }
+ }
+ catch (RuntimeException & exc)
+ {
+ SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc);
+ if (! bIgnoreRuntimeExceptionsWhileFiring)
+ throw;
+ }
+ }
+}
+
+// OPropertySetHelper
+void OPropertySetHelper::setFastPropertyValues(
+ sal_Int32 nSeqLen,
+ sal_Int32 * pHandles,
+ const Any * pValues,
+ sal_Int32 nHitCount )
+{
+ OSL_ENSURE( !rBHelper.bInDispose, "do not getFastPropertyValue in the dispose call" );
+ OSL_ENSURE( !rBHelper.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;
+
+ {
+ // must lock the mutex outside the loop. So all values are consistent.
+ MutexGuard aGuard( rBHelper.rMutex );
+ 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( pConvertedValues[ n ], pOldValues[n],
+ pHandles[i], pValues[i] ) )
+ {
+ // only increment if the property really change
+ pHandles[n] = pHandles[i];
+ n++;
+ }
+ }
+ }
+ // release guard to fire events
+ }
+
+ // fire vetoable events
+ fire( pHandles, pConvertedValues.get(), pOldValues.get(), n, true );
+
+ {
+ // must lock the mutex outside the loop.
+ MutexGuard aGuard( rBHelper.rMutex );
+ // Loop over all changed properties
+ for( i = 0; i < n; i++ )
+ {
+ // Will the property change?
+ setFastPropertyValue_NoBroadcast( pHandles[i], pConvertedValues[i] );
+ }
+ // release guard to fire events
+ }
+
+ // fire change events
+ impl_fireAll( 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();
+ 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 )
+ setFastPropertyValues( 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();
+
+ MutexGuard aGuard( rBHelper.rMutex );
+ // fill the sequence with the values
+ for( sal_Int32 i = 0; i < nSeqLen; i++ )
+ getFastPropertyValue( pValues[i], pHandles[i] );
+
+ return aValues;
+}
+
+// XMultiPropertySet
+void OPropertySetHelper::addPropertiesChangeListener(
+ const Sequence<OUString> & ,
+ const Reference < XPropertiesChangeListener > & rListener )
+{
+ rBHelper.addListener( cppu::UnoType<decltype(rListener)>::get(), rListener );
+}
+
+// XMultiPropertySet
+void OPropertySetHelper::removePropertiesChangeListener(
+ const Reference < XPropertiesChangeListener > & rListener )
+{
+ rBHelper.removeListener( cppu::UnoType<decltype(rListener)>::get(), rListener );
+}
+
+// XMultiPropertySet
+void OPropertySetHelper::firePropertiesChangeEvent(
+ const Sequence<OUString>& rPropertyNames,
+ const Reference < XPropertiesChangeListener >& rListener )
+{
+ sal_Int32 nLen = rPropertyNames.getLength();
+ std::unique_ptr<sal_Int32[]> pHandles(new sal_Int32[nLen]);
+ IPropertyArrayHelper & rPH = getInfoHelper();
+ rPH.fillHandles( pHandles.get(), rPropertyNames );
+ const OUString* pNames = rPropertyNames.getConstArray();
+
+ // get the count of matching properties
+ sal_Int32 nFireLen = 0;
+ sal_Int32 i;
+ for( i = 0; i < nLen; i++ )
+ if( pHandles[i] != -1 )
+ nFireLen++;
+
+ Sequence<PropertyChangeEvent> aChanges( nFireLen );
+ PropertyChangeEvent* pChanges = aChanges.getArray();
+
+ {
+ // must lock the mutex outside the loop. So all values are consistent.
+ MutexGuard aGuard( rBHelper.rMutex );
+ Reference < XInterface > xSource( static_cast<XPropertySet *>(this), UNO_QUERY );
+ sal_Int32 nFirePos = 0;
+ for( i = 0; i < nLen; i++ )
+ {
+ if( pHandles[i] != -1 )
+ {
+ pChanges[nFirePos].Source = xSource;
+ pChanges[nFirePos].PropertyName = pNames[i];
+ pChanges[nFirePos].PropertyHandle = pHandles[i];
+ getFastPropertyValue( pChanges[nFirePos].OldValue, pHandles[i] );
+ pChanges[nFirePos].NewValue = pChanges[nFirePos].OldValue;
+ nFirePos++;
+ }
+ }
+ // release guard to fire events
+ }
+ if( nFireLen )
+ rListener->propertiesChange( aChanges );
+}
+
+void OPropertySetHelper2::enableChangeListenerNotification( sal_Bool bEnable )
+{
+ m_pReserved->m_bFireEvents = bEnable;
+}
+
+extern "C" {
+
+static int compare_Property_Impl( const void *arg1, const void *arg2 )
+ SAL_THROW_EXTERN_C()
+{
+ return static_cast<Property const *>(arg1)->Name.compareTo( static_cast<Property const *>(arg2)->Name );
+}
+
+}
+
+void OPropertyArrayHelper::init( sal_Bool bSorted )
+{
+ sal_Int32 i, nElements = aInfos.getLength();
+ const Property* pProperties = aInfos.getConstArray();
+
+ for( i = 1; i < nElements; i++ )
+ {
+ if( pProperties[i-1].Name > pProperties[i].Name )
+ {
+ if (bSorted) {
+ OSL_FAIL( "Property array is not sorted" );
+ }
+ // not sorted
+ qsort( aInfos.getArray(), nElements, sizeof( Property ),
+ compare_Property_Impl );
+ pProperties = aInfos.getConstArray();
+ break;
+ }
+ }
+ for( i = 0; i < nElements; i++ )
+ if( pProperties[i].Handle != i )
+ return;
+ // The handle is the index
+ bRightOrdered = true;
+}
+
+OPropertyArrayHelper::OPropertyArrayHelper(
+ Property * pProps,
+ sal_Int32 nEle,
+ sal_Bool bSorted )
+ : m_pReserved(nullptr)
+ , aInfos(pProps, nEle)
+ , bRightOrdered( false )
+{
+ init( bSorted );
+}
+
+OPropertyArrayHelper::OPropertyArrayHelper(
+ const Sequence< Property > & aProps,
+ sal_Bool bSorted )
+ : m_pReserved(nullptr)
+ , aInfos(aProps)
+ , bRightOrdered( false )
+{
+ init( bSorted );
+}
+
+
+sal_Int32 OPropertyArrayHelper::getCount() const
+{
+ return aInfos.getLength();
+}
+
+
+sal_Bool OPropertyArrayHelper::fillPropertyMembersByHandle
+(
+ OUString * pPropName,
+ sal_Int16 * pAttributes,
+ sal_Int32 nHandle
+)
+{
+ const Property* pProperties = aInfos.getConstArray();
+ sal_Int32 nElements = aInfos.getLength();
+
+ if( bRightOrdered )
+ {
+ if( nHandle < 0 || nHandle >= nElements )
+ return false;
+ if( pPropName )
+ *pPropName = pProperties[ nHandle ].Name;
+ if( pAttributes )
+ *pAttributes = pProperties[ nHandle ].Attributes;
+ return true;
+ }
+ // normally the array is sorted
+ for( sal_Int32 i = 0; i < nElements; i++ )
+ {
+ if( pProperties[i].Handle == nHandle )
+ {
+ if( pPropName )
+ *pPropName = pProperties[ i ].Name;
+ if( pAttributes )
+ *pAttributes = pProperties[ i ].Attributes;
+ return true;
+ }
+ }
+ return false;
+}
+
+
+Sequence< Property > OPropertyArrayHelper::getProperties()
+{
+ return aInfos;
+}
+
+
+Property OPropertyArrayHelper::getPropertyByName(const OUString& aPropertyName)
+{
+ Property * pR;
+ pR = static_cast<Property *>(bsearch( &aPropertyName, aInfos.getConstArray(), aInfos.getLength(),
+ sizeof( Property ),
+ compare_OUString_Property_Impl ));
+ if( !pR ) {
+ throw UnknownPropertyException(aPropertyName);
+ }
+ return *pR;
+}
+
+
+sal_Bool OPropertyArrayHelper::hasPropertyByName(const OUString& aPropertyName)
+{
+ Property * pR;
+ pR = static_cast<Property *>(bsearch( &aPropertyName, aInfos.getConstArray(), aInfos.getLength(),
+ sizeof( Property ),
+ compare_OUString_Property_Impl ));
+ return pR != nullptr;
+}
+
+
+sal_Int32 OPropertyArrayHelper::getHandleByName( const OUString & rPropName )
+{
+ Property * pR;
+ pR = static_cast<Property *>(bsearch( &rPropName, aInfos.getConstArray(), aInfos.getLength(),
+ sizeof( Property ),
+ compare_OUString_Property_Impl ));
+ return pR ? pR->Handle : -1;
+}
+
+
+sal_Int32 OPropertyArrayHelper::fillHandles( sal_Int32 * pHandles, const Sequence< OUString > & rPropNames )
+{
+ sal_Int32 nHitCount = 0;
+ const OUString * pReqProps = rPropNames.getConstArray();
+ sal_Int32 nReqLen = rPropNames.getLength();
+ const Property * pCur = aInfos.getConstArray();
+ const Property * pEnd = pCur + aInfos.getLength();
+
+ for( sal_Int32 i = 0; i < nReqLen; i++ )
+ {
+ // Calculate logarithm
+ sal_Int32 n = static_cast<sal_Int32>(pEnd - pCur);
+ sal_Int32 nLog = 0;
+ while( n )
+ {
+ nLog += 1;
+ n = n >> 1;
+ }
+
+ // Number of properties to search for * Log2 of the number of remaining
+ // properties to search in.
+ if( (nReqLen - i) * nLog >= pEnd - pCur )
+ {
+ // linear search is better
+ while( pCur < pEnd && pReqProps[i] > pCur->Name )
+ {
+ pCur++;
+ }
+ if( pCur < pEnd && pReqProps[i] == pCur->Name )
+ {
+ pHandles[i] = pCur->Handle;
+ nHitCount++;
+ }
+ else
+ pHandles[i] = -1;
+ }
+ else
+ {
+ // binary search is better
+ sal_Int32 nCompVal = 1;
+ const Property * pOldEnd = pEnd--;
+ const Property * pMid = pCur;
+
+ while( nCompVal != 0 && pCur <= pEnd )
+ {
+ pMid = (pEnd - pCur) / 2 + pCur;
+
+ nCompVal = pReqProps[i].compareTo( pMid->Name );
+
+ if( nCompVal > 0 )
+ pCur = pMid + 1;
+ else
+ pEnd = pMid - 1;
+ }
+
+ if( nCompVal == 0 )
+ {
+ pHandles[i] = pMid->Handle;
+ nHitCount++;
+ pCur = pMid +1;
+ }
+ else if( nCompVal > 0 )
+ {
+ pHandles[i] = -1;
+ pCur = pMid +1;
+ }
+ else
+ {
+ pHandles[i] = -1;
+ pCur = pMid;
+ }
+ pEnd = pOldEnd;
+ }
+ }
+ return nHitCount;
+}
+
+} // end namespace cppu
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/servicemanager.cxx b/cppuhelper/source/servicemanager.cxx
new file mode 100644
index 000000000..5bcd2dfee
--- /dev/null
+++ b/cppuhelper/source/servicemanager.cxx
@@ -0,0 +1,2020 @@
+/* -*- 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 <algorithm>
+#include <cassert>
+#include <iostream>
+#include <mutex>
+#include <string_view>
+#include <utility>
+#include <vector>
+
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/container/ElementExistException.hpp>
+#include <com/sun/star/container/XEnumeration.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XSingleComponentFactory.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/loader/XImplementationLoader.hpp>
+#include <com/sun/star/registry/InvalidRegistryException.hpp>
+#include <com/sun/star/uno/DeploymentException.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/bootstrap.hxx>
+#include <cppuhelper/component_context.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/factory.hxx>
+#include <o3tl/safeint.hxx>
+#include <osl/file.hxx>
+#include <osl/module.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/uri.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <uno/environment.hxx>
+#include <uno/mapping.hxx>
+#include <o3tl/string_view.hxx>
+
+#include "loadsharedlibcomponentfactory.hxx"
+
+#include <registry/registry.hxx>
+#include <xmlreader/xmlreader.hxx>
+
+#include "paths.hxx"
+#include "servicemanager.hxx"
+
+namespace {
+
+void insertImplementationMap(
+ cppuhelper::ServiceManager::Data::ImplementationMap * destination,
+ cppuhelper::ServiceManager::Data::ImplementationMap const & source)
+{
+ assert(destination != nullptr);
+ for (const auto& [rName, rImpls] : source)
+ {
+ std::vector<
+ std::shared_ptr<
+ cppuhelper::ServiceManager::Data::Implementation > > & impls
+ = (*destination)[rName];
+ impls.insert(impls.end(), rImpls.begin(), rImpls.end());
+ }
+}
+
+void removeFromImplementationMap(
+ cppuhelper::ServiceManager::Data::ImplementationMap * map,
+ std::vector< OUString > const & elements,
+ std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
+ const & implementation)
+{
+ // The underlying data structures make this function somewhat inefficient,
+ // but the assumption is that it is rarely called:
+ assert(map != nullptr);
+ for (const auto& rElement : elements)
+ {
+ cppuhelper::ServiceManager::Data::ImplementationMap::iterator j(
+ map->find(rElement));
+ assert(j != map->end());
+ std::vector<
+ std::shared_ptr<
+ cppuhelper::ServiceManager::Data::Implementation > >::iterator
+ k(std::find(j->second.begin(), j->second.end(), implementation));
+ assert(k != j->second.end());
+ j->second.erase(k);
+ if (j->second.empty()) {
+ map->erase(j);
+ }
+ }
+}
+
+// For simplicity, this code keeps throwing
+// css::registry::InvalidRegistryException for invalid XML rdbs (even though
+// that does not fit the exception's name):
+class Parser {
+public:
+ Parser(
+ OUString const & uri,
+ css::uno::Reference< css::uno::XComponentContext > alienContext,
+ cppuhelper::ServiceManager::Data * data);
+
+ Parser(const Parser&) = delete;
+ const Parser& operator=(const Parser&) = delete;
+
+private:
+ void handleComponent();
+
+ void handleImplementation();
+
+ void handleService();
+
+ void handleSingleton();
+
+ OUString getNameAttribute();
+
+ xmlreader::XmlReader reader_;
+ css::uno::Reference< css::uno::XComponentContext > alienContext_;
+ cppuhelper::ServiceManager::Data * data_;
+ OUString attrLoader_;
+ OUString attrUri_;
+ OUString attrEnvironment_;
+ OUString attrPrefix_;
+ std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
+ implementation_;
+};
+
+Parser::Parser(
+ OUString const & uri,
+ css::uno::Reference< css::uno::XComponentContext > alienContext,
+ cppuhelper::ServiceManager::Data * data):
+ reader_(uri), alienContext_(std::move(alienContext)), data_(data)
+{
+ assert(data != nullptr);
+ int ucNsId = reader_.registerNamespaceIri(
+ xmlreader::Span(
+ RTL_CONSTASCII_STRINGPARAM(
+ "http://openoffice.org/2010/uno-components")));
+ enum State {
+ STATE_BEGIN, STATE_END, STATE_COMPONENTS, STATE_COMPONENT_INITIAL,
+ STATE_COMPONENT, STATE_IMPLEMENTATION, STATE_SERVICE, STATE_SINGLETON };
+ for (State state = STATE_BEGIN;;) {
+ xmlreader::Span name;
+ int nsId;
+ xmlreader::XmlReader::Result res = reader_.nextItem(
+ xmlreader::XmlReader::Text::NONE, &name, &nsId);
+ switch (state) {
+ case STATE_BEGIN:
+ if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("components")))
+ {
+ state = STATE_COMPONENTS;
+ break;
+ }
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": unexpected item in outer level");
+ case STATE_END:
+ if (res == xmlreader::XmlReader::Result::Done) {
+ return;
+ }
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": unexpected item in outer level");
+ case STATE_COMPONENTS:
+ if (res == xmlreader::XmlReader::Result::End) {
+ state = STATE_END;
+ break;
+ }
+ if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("component")))
+ {
+ handleComponent();
+ state = STATE_COMPONENT_INITIAL;
+ break;
+ }
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": unexpected item in <components>");
+ case STATE_COMPONENT:
+ if (res == xmlreader::XmlReader::Result::End) {
+ state = STATE_COMPONENTS;
+ break;
+ }
+ [[fallthrough]];
+ case STATE_COMPONENT_INITIAL:
+ if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("implementation")))
+ {
+ handleImplementation();
+ state = STATE_IMPLEMENTATION;
+ break;
+ }
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": unexpected item in <component>");
+ case STATE_IMPLEMENTATION:
+ if (res == xmlreader::XmlReader::Result::End) {
+ state = STATE_COMPONENT;
+ break;
+ }
+ if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("service")))
+ {
+ handleService();
+ state = STATE_SERVICE;
+ break;
+ }
+ if (res == xmlreader::XmlReader::Result::Begin && nsId == ucNsId
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("singleton")))
+ {
+ handleSingleton();
+ state = STATE_SINGLETON;
+ break;
+ }
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": unexpected item in <implementation>");
+ case STATE_SERVICE:
+ if (res == xmlreader::XmlReader::Result::End) {
+ state = STATE_IMPLEMENTATION;
+ break;
+ }
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": unexpected item in <service>");
+ case STATE_SINGLETON:
+ if (res == xmlreader::XmlReader::Result::End) {
+ state = STATE_IMPLEMENTATION;
+ break;
+ }
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": unexpected item in <service>");
+ }
+ }
+}
+
+void Parser::handleComponent() {
+ attrLoader_ = OUString();
+ attrUri_ = OUString();
+ attrEnvironment_ = OUString();
+ attrPrefix_ = OUString();
+ xmlreader::Span name;
+ int nsId;
+ while (reader_.nextAttribute(&nsId, &name)) {
+ if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("loader")))
+ {
+ if (!attrLoader_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl()
+ + ": <component> has multiple \"loader\" attributes");
+ }
+ attrLoader_ = reader_.getAttributeValue(false).convertFromUtf8();
+ if (attrLoader_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl()
+ + ": <component> has empty \"loader\" attribute");
+ }
+ } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("uri")))
+ {
+ if (!attrUri_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl()
+ + ": <component> has multiple \"uri\" attributes");
+ }
+ attrUri_ = reader_.getAttributeValue(false).convertFromUtf8();
+ if (attrUri_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl()
+ + ": <component> has empty \"uri\" attribute");
+ }
+ } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("environment")))
+ {
+ if (!attrEnvironment_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() +
+ ": <component> has multiple \"environment\" attributes");
+ }
+ attrEnvironment_ = reader_.getAttributeValue(false)
+ .convertFromUtf8();
+ if (attrEnvironment_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() +
+ ": <component> has empty \"environment\" attribute");
+ }
+ } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("prefix")))
+ {
+ if (!attrPrefix_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() +
+ ": <component> has multiple \"prefix\" attributes");
+ }
+ attrPrefix_ = reader_.getAttributeValue(false).convertFromUtf8();
+ if (attrPrefix_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() +
+ ": <component> has empty \"prefix\" attribute");
+ }
+ } else {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": unexpected attribute \""
+ + name.convertFromUtf8() + "\" in <component>");
+ }
+ }
+ if (attrLoader_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": <component> is missing \"loader\" attribute");
+ }
+ if (attrUri_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": <component> is missing \"uri\" attribute");
+ }
+#ifndef DISABLE_DYNLOADING
+ try {
+ attrUri_ = rtl::Uri::convertRelToAbs(reader_.getUrl(), attrUri_);
+ } catch (const rtl::MalformedUriException & e) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": bad \"uri\" attribute: " + e.getMessage());
+ }
+#endif
+}
+
+void Parser::handleImplementation() {
+ OUString attrName;
+ OUString attrConstructor;
+ bool attrSingleInstance = false;
+ xmlreader::Span name;
+ int nsId;
+ while (reader_.nextAttribute(&nsId, &name)) {
+ if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("name")))
+ {
+ if (!attrName.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl()
+ + ": <implementation> has multiple \"name\" attributes");
+ }
+ attrName = reader_.getAttributeValue(false).convertFromUtf8();
+ if (attrName.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl()
+ + ": <implementation> has empty \"name\" attribute");
+ }
+ } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("constructor")))
+ {
+ if (!attrConstructor.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl()
+ + ": <implementation> has multiple \"constructor\""
+ " attributes");
+ }
+ attrConstructor = reader_.getAttributeValue(false)
+ .convertFromUtf8();
+ if (attrConstructor.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl()
+ + ": element has empty \"constructor\" attribute");
+ }
+ if (attrEnvironment_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl()
+ + ": <implementation> has \"constructor\" attribute but"
+ " <component> has no \"environment\" attribute");
+ }
+ } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("single-instance")))
+ {
+ if (attrSingleInstance) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl()
+ + ": <implementation> has multiple \"single-instance\" attributes");
+ }
+ if (!reader_.getAttributeValue(false).equals(RTL_CONSTASCII_STRINGPARAM("true"))) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": <implementation> has bad \"single-instance\" attribute");
+ }
+ attrSingleInstance = true;
+ } else {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": unexpected element attribute \""
+ + name.convertFromUtf8() + "\" in <implementation>");
+ }
+ }
+ if (attrName.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl()
+ + ": <implementation> is missing \"name\" attribute");
+ }
+ implementation_ =
+ std::make_shared<cppuhelper::ServiceManager::Data::Implementation>(
+ attrName, attrLoader_, attrUri_, attrEnvironment_, attrConstructor,
+ attrPrefix_, attrSingleInstance, alienContext_, reader_.getUrl());
+ if (!data_->namedImplementations.emplace(attrName, implementation_).
+ second)
+ {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": duplicate <implementation name=\"" + attrName
+ + "\">");
+ }
+}
+
+void Parser::handleService() {
+ OUString name(getNameAttribute());
+ implementation_->services.push_back(name);
+ data_->services[name].push_back(implementation_);
+}
+
+void Parser::handleSingleton() {
+ OUString name(getNameAttribute());
+ implementation_->singletons.push_back(name);
+ data_->singletons[name].push_back(implementation_);
+}
+
+OUString Parser::getNameAttribute() {
+ OUString attrName;
+ xmlreader::Span name;
+ int nsId;
+ while (reader_.nextAttribute(&nsId, &name)) {
+ if (nsId != xmlreader::XmlReader::NAMESPACE_NONE
+ || !name.equals(RTL_CONSTASCII_STRINGPARAM("name")))
+ {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": expected element attribute \"name\"");
+ }
+ if (!attrName.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl()
+ + ": element has multiple \"name\" attributes");
+ }
+ attrName = reader_.getAttributeValue(false).convertFromUtf8();
+ if (attrName.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": element has empty \"name\" attribute");
+ }
+ }
+ if (attrName.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": element is missing \"name\" attribute");
+ }
+ return attrName;
+}
+
+class ContentEnumeration:
+ public cppu::WeakImplHelper< css::container::XEnumeration >
+{
+public:
+ explicit ContentEnumeration(std::vector< css::uno::Any >&& factories):
+ factories_(std::move(factories)), iterator_(factories_.begin()) {}
+
+ ContentEnumeration(const ContentEnumeration&) = delete;
+ const ContentEnumeration& operator=(const ContentEnumeration&) = delete;
+
+private:
+ virtual ~ContentEnumeration() override {}
+
+ virtual sal_Bool SAL_CALL hasMoreElements() override;
+
+ virtual css::uno::Any SAL_CALL nextElement() override;
+
+ std::mutex mutex_;
+ std::vector< css::uno::Any > factories_;
+ std::vector< css::uno::Any >::const_iterator iterator_;
+};
+
+sal_Bool ContentEnumeration::hasMoreElements()
+{
+ std::scoped_lock g(mutex_);
+ return iterator_ != factories_.end();
+}
+
+css::uno::Any ContentEnumeration::nextElement()
+{
+ std::scoped_lock g(mutex_);
+ if (iterator_ == factories_.end()) {
+ throw css::container::NoSuchElementException(
+ "Bootstrap service manager service enumerator has no more elements",
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ return *iterator_++;
+}
+
+css::beans::Property getDefaultContextProperty() {
+ return css::beans::Property(
+ "DefaultContext", -1,
+ cppu::UnoType< css::uno::XComponentContext >::get(),
+ css::beans::PropertyAttribute::READONLY);
+}
+
+class SingletonFactory:
+ public cppu::WeakImplHelper<css::lang::XSingleComponentFactory>
+{
+public:
+ SingletonFactory(
+ rtl::Reference< cppuhelper::ServiceManager > const & manager,
+ std::shared_ptr<
+ cppuhelper::ServiceManager::Data::Implementation > const &
+ implementation):
+ manager_(manager), implementation_(implementation)
+ { assert(manager.is()); assert(implementation); }
+
+ SingletonFactory(const SingletonFactory&) = delete;
+ const SingletonFactory& operator=(const SingletonFactory&) = delete;
+
+private:
+ virtual ~SingletonFactory() override {}
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithContext(
+ css::uno::Reference< css::uno::XComponentContext > const & Context) override;
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithArgumentsAndContext(
+ css::uno::Sequence< css::uno::Any > const & Arguments,
+ css::uno::Reference< css::uno::XComponentContext > const & Context) override;
+
+ rtl::Reference< cppuhelper::ServiceManager > manager_;
+ std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
+ implementation_;
+};
+
+css::uno::Reference< css::uno::XInterface >
+SingletonFactory::createInstanceWithContext(
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+{
+ manager_->loadImplementation(Context, implementation_);
+ return implementation_->createInstance(Context, true);
+}
+
+css::uno::Reference< css::uno::XInterface >
+SingletonFactory::createInstanceWithArgumentsAndContext(
+ css::uno::Sequence< css::uno::Any > const & Arguments,
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+{
+ manager_->loadImplementation(Context, implementation_);
+ return implementation_->createInstanceWithArguments(
+ Context, true, Arguments);
+}
+
+class ImplementationWrapper:
+ public cppu::WeakImplHelper<
+ css::lang::XSingleComponentFactory, css::lang::XSingleServiceFactory,
+ css::lang::XServiceInfo >
+{
+public:
+ ImplementationWrapper(
+ rtl::Reference< cppuhelper::ServiceManager > const & manager,
+ std::shared_ptr<
+ cppuhelper::ServiceManager::Data::Implementation > const &
+ implementation):
+ manager_(manager), implementation_(implementation)
+ { assert(manager.is()); assert(implementation); }
+
+ ImplementationWrapper(const ImplementationWrapper&) = delete;
+ const ImplementationWrapper& operator=(const ImplementationWrapper&) = delete;
+
+private:
+ virtual ~ImplementationWrapper() override {}
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithContext(
+ css::uno::Reference< css::uno::XComponentContext > const & Context) override;
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithArgumentsAndContext(
+ css::uno::Sequence< css::uno::Any > const & Arguments,
+ css::uno::Reference< css::uno::XComponentContext > const & Context) override;
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstance() override;
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithArguments(
+ css::uno::Sequence< css::uno::Any > const & Arguments) override;
+
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedServiceNames() override;
+
+ rtl::Reference< cppuhelper::ServiceManager > manager_;
+ std::weak_ptr< cppuhelper::ServiceManager::Data::Implementation >
+ implementation_;
+};
+
+css::uno::Reference< css::uno::XInterface >
+ImplementationWrapper::createInstanceWithContext(
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+{
+ std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
+ assert(impl);
+ manager_->loadImplementation(Context, impl);
+ return impl->createInstance(Context, false);
+}
+
+css::uno::Reference< css::uno::XInterface >
+ImplementationWrapper::createInstanceWithArgumentsAndContext(
+ css::uno::Sequence< css::uno::Any > const & Arguments,
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+{
+ std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
+ assert(impl);
+ manager_->loadImplementation(Context, impl);
+ return impl->createInstanceWithArguments(
+ Context, false, Arguments);
+}
+
+css::uno::Reference< css::uno::XInterface >
+ImplementationWrapper::createInstance()
+{
+ return createInstanceWithContext(manager_->getContext());
+}
+
+css::uno::Reference< css::uno::XInterface >
+ImplementationWrapper::createInstanceWithArguments(
+ css::uno::Sequence< css::uno::Any > const & Arguments)
+{
+ return createInstanceWithArgumentsAndContext(
+ Arguments, manager_->getContext());
+}
+
+OUString ImplementationWrapper::getImplementationName()
+{
+ std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
+ assert(impl);
+ return impl->name;
+}
+
+sal_Bool ImplementationWrapper::supportsService(OUString const & ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+css::uno::Sequence< OUString >
+ImplementationWrapper::getSupportedServiceNames()
+{
+ std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = implementation_.lock();
+ assert(impl);
+ if (impl->services.size()
+ > o3tl::make_unsigned(SAL_MAX_INT32))
+ {
+ throw css::uno::RuntimeException(
+ ("Implementation " + impl->name
+ + " supports too many services"),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ return comphelper::containerToSequence(impl->services);
+}
+
+}
+
+css::uno::Reference<css::uno::XInterface>
+cppuhelper::ServiceManager::Data::Implementation::createInstance(
+ css::uno::Reference<css::uno::XComponentContext> const & context,
+ bool singletonRequest)
+{
+ css::uno::Reference<css::uno::XInterface> inst;
+ if (isSingleInstance) {
+ std::unique_lock g(mutex);
+ if (!singleInstance.is()) {
+ singleInstance = doCreateInstance(context);
+ }
+ inst = singleInstance;
+ } else {
+ inst = doCreateInstance(context);
+ }
+ updateDisposeInstance(singletonRequest, inst);
+ return inst;
+}
+
+css::uno::Reference<css::uno::XInterface>
+cppuhelper::ServiceManager::Data::Implementation::createInstanceWithArguments(
+ css::uno::Reference<css::uno::XComponentContext> const & context,
+ bool singletonRequest, css::uno::Sequence<css::uno::Any> const & arguments)
+{
+ css::uno::Reference<css::uno::XInterface> inst;
+ if (isSingleInstance) {
+ std::unique_lock g(mutex);
+ if (!singleInstance.is()) {
+ singleInstance = doCreateInstanceWithArguments(context, arguments);
+ }
+ inst = singleInstance;
+ } else {
+ inst = doCreateInstanceWithArguments(context, arguments);
+ }
+ updateDisposeInstance(singletonRequest, inst);
+ return inst;
+}
+
+css::uno::Reference<css::uno::XInterface>
+cppuhelper::ServiceManager::Data::Implementation::doCreateInstance(
+ css::uno::Reference<css::uno::XComponentContext> const & context)
+{
+ if (constructorFn) {
+ return css::uno::Reference<css::uno::XInterface>(
+ constructorFn(context.get(), css::uno::Sequence<css::uno::Any>()),
+ SAL_NO_ACQUIRE);
+ } else if (factory1.is()) {
+ return factory1->createInstanceWithContext(context);
+ } else {
+ assert(factory2.is());
+ return factory2->createInstance();
+ }
+}
+
+css::uno::Reference<css::uno::XInterface>
+cppuhelper::ServiceManager::Data::Implementation::doCreateInstanceWithArguments(
+ css::uno::Reference<css::uno::XComponentContext> const & context,
+ css::uno::Sequence<css::uno::Any> const & arguments)
+{
+ if (constructorFn) {
+ css::uno::Reference<css::uno::XInterface> inst(
+ constructorFn(context.get(), arguments), SAL_NO_ACQUIRE);
+ //HACK: The constructor will either observe arguments and return inst
+ // that does not implement XInitialization (or null), or ignore
+ // arguments and return inst that implements XInitialization; this
+ // should be removed again once XInitialization-based implementations
+ // have become rare:
+ css::uno::Reference<css::lang::XInitialization> init(
+ inst, css::uno::UNO_QUERY);
+ if (init.is()) {
+ init->initialize(arguments);
+ }
+ return inst;
+ } else if (factory1.is()) {
+ return factory1->createInstanceWithArgumentsAndContext(
+ arguments, context);
+ } else {
+ assert(factory2.is());
+ return factory2->createInstanceWithArguments(arguments);
+ }
+}
+
+void cppuhelper::ServiceManager::Data::Implementation::updateDisposeInstance(
+ bool singletonRequest,
+ css::uno::Reference<css::uno::XInterface> const & instance)
+{
+ // This is an optimization, to only call dispose once (from the component
+ // context) on a singleton that is obtained both via the component context
+ // and via the service manager; however, there is a harmless race here that
+ // may cause two calls to dispose nevertheless (also, this calls dispose on
+ // at most one of the instances obtained via the service manager, in case
+ // the implementation hands out different instances):
+ if (singletonRequest) {
+ std::unique_lock g(mutex);
+ disposeInstance.clear();
+ dispose = false;
+ } else if (shallDispose()) {
+ css::uno::Reference<css::lang::XComponent> comp(
+ instance, css::uno::UNO_QUERY);
+ if (comp.is()) {
+ std::unique_lock g(mutex);
+ if (dispose) {
+ disposeInstance = comp;
+ }
+ }
+ }
+}
+
+void cppuhelper::ServiceManager::addSingletonContextEntries(
+ std::vector< cppu::ContextEntry_Init > * entries)
+{
+ assert(entries != nullptr);
+ for (const auto& [rName, rImpls] : data_.singletons)
+ {
+ assert(!rImpls.empty());
+ assert(rImpls[0]);
+ SAL_INFO_IF(
+ rImpls.size() > 1, "cppuhelper",
+ "Arbitrarily choosing " << rImpls[0]->name
+ << " among multiple implementations for " << rName);
+ entries->push_back(
+ cppu::ContextEntry_Init(
+ "/singletons/" + rName,
+ css::uno::Any(
+ css::uno::Reference<css::lang::XSingleComponentFactory>(
+ new SingletonFactory(this, rImpls[0]))),
+ true));
+ }
+}
+
+void cppuhelper::ServiceManager::loadImplementation(
+ css::uno::Reference< css::uno::XComponentContext > const & context,
+ std::shared_ptr< Data::Implementation > const & implementation)
+{
+ assert(implementation);
+ {
+ osl::MutexGuard g(rBHelper.rMutex);
+ if (implementation->status == Data::Implementation::STATUS_LOADED) {
+ return;
+ }
+ }
+ OUString uri;
+ try {
+ uri = cppu::bootstrap_expandUri(implementation->uri);
+ } catch (css::lang::IllegalArgumentException & e) {
+ throw css::uno::DeploymentException(
+ "Cannot expand URI" + implementation->uri + ": " + e.Message,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ cppuhelper::WrapperConstructorFn ctor;
+ css::uno::Reference< css::uno::XInterface > f0;
+ // Special handling of SharedLibrary loader, with support for environment,
+ // constructor, and prefix arguments:
+ if (!implementation->alienContext.is()
+ && implementation->loader == "com.sun.star.loader.SharedLibrary")
+ {
+ cppuhelper::detail::loadSharedLibComponentFactory(
+ uri, implementation->environment,
+ implementation->prefix, implementation->name,
+ implementation->constructorName, this, &ctor, &f0);
+ if (ctor) {
+ assert(!implementation->environment.isEmpty());
+ }
+ } else {
+ SAL_WARN_IF(
+ !implementation->environment.isEmpty(), "cppuhelper",
+ "Loader " << implementation->loader
+ << " and non-empty environment "
+ << implementation->environment);
+ SAL_WARN_IF(
+ !implementation->prefix.isEmpty(), "cppuhelper",
+ "Loader " << implementation->loader
+ << " and non-empty constructor "
+ << implementation->constructorName);
+ SAL_WARN_IF(
+ !implementation->prefix.isEmpty(), "cppuhelper",
+ "Loader " << implementation->loader
+ << " and non-empty prefix " << implementation->prefix);
+ css::uno::Reference< css::uno::XComponentContext > ctxt;
+ css::uno::Reference< css::lang::XMultiComponentFactory > smgr;
+ if (implementation->alienContext.is()) {
+ ctxt = implementation->alienContext;
+ smgr.set(ctxt->getServiceManager(), css::uno::UNO_SET_THROW);
+ } else {
+ assert(context.is());
+ ctxt = context;
+ smgr = this;
+ }
+ css::uno::Reference< css::loader::XImplementationLoader > loader(
+ smgr->createInstanceWithContext(implementation->loader, ctxt),
+ css::uno::UNO_QUERY_THROW);
+ f0 = loader->activate(
+ implementation->name, OUString(), uri,
+ css::uno::Reference< css::registry::XRegistryKey >());
+ }
+ css::uno::Reference<css::lang::XSingleComponentFactory> f1;
+ css::uno::Reference<css::lang::XSingleServiceFactory> f2;
+ if (!ctor) {
+ f1.set(f0, css::uno::UNO_QUERY);
+ if (!f1.is()) {
+ f2.set(f0, css::uno::UNO_QUERY);
+ if (!f2.is()) {
+ throw css::uno::DeploymentException(
+ ("Implementation " + implementation->name
+ + " does not provide a constructor or factory"),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ }
+ }
+ //TODO: There is a race here, as the relevant service factory can be removed
+ // while the mutex is unlocked and loading can thus fail, as the entity from
+ // which to load can disappear once the service factory is removed.
+ osl::MutexGuard g(rBHelper.rMutex);
+ if (!(isDisposed()
+ || implementation->status == Data::Implementation::STATUS_LOADED))
+ {
+ implementation->status = Data::Implementation::STATUS_LOADED;
+ implementation->constructorFn = ctor;
+ implementation->factory1 = f1;
+ implementation->factory2 = f2;
+ }
+}
+
+void cppuhelper::ServiceManager::disposing() {
+ std::vector< css::uno::Reference<css::lang::XComponent> > sngls;
+ std::vector< css::uno::Reference< css::lang::XComponent > > comps;
+ Data clear;
+ {
+ osl::MutexGuard g(rBHelper.rMutex);
+ for (const auto& rEntry : data_.namedImplementations)
+ {
+ assert(rEntry.second);
+ if (rEntry.second->shallDispose()) {
+ std::unique_lock g2(rEntry.second->mutex);
+ if (rEntry.second->disposeInstance.is()) {
+ sngls.push_back(rEntry.second->disposeInstance);
+ }
+ }
+ }
+ for (const auto& rEntry : data_.dynamicImplementations)
+ {
+ assert(rEntry.second);
+ if (rEntry.second->shallDispose()) {
+ std::unique_lock g2(rEntry.second->mutex);
+ if (rEntry.second->disposeInstance.is()) {
+ sngls.push_back(rEntry.second->disposeInstance);
+ }
+ }
+ if (rEntry.second->component.is()) {
+ comps.push_back(rEntry.second->component);
+ }
+ }
+ data_.namedImplementations.swap(clear.namedImplementations);
+ data_.dynamicImplementations.swap(clear.dynamicImplementations);
+ data_.services.swap(clear.services);
+ data_.singletons.swap(clear.singletons);
+ }
+ for (const auto& rxSngl : sngls)
+ {
+ try {
+ rxSngl->dispose();
+ } catch (css::uno::RuntimeException & e) {
+ SAL_WARN("cppuhelper", "Ignoring " << e << " while disposing singleton");
+ }
+ }
+ for (const auto& rxComp : comps)
+ {
+ removeEventListenerFromComponent(rxComp);
+ }
+}
+
+void cppuhelper::ServiceManager::initialize(
+ css::uno::Sequence<css::uno::Any> const & aArguments)
+{
+ OUString arg;
+ if (aArguments.getLength() != 1 || !(aArguments[0] >>= arg)
+ || arg != "preload")
+ {
+ throw css::lang::IllegalArgumentException(
+ "invalid ServiceManager::initialize argument",
+ css::uno::Reference<css::uno::XInterface>(), 0);
+ }
+ preloadImplementations();
+}
+
+OUString cppuhelper::ServiceManager::getImplementationName()
+{
+ return
+ "com.sun.star.comp.cppuhelper.bootstrap.ServiceManager";
+}
+
+sal_Bool cppuhelper::ServiceManager::supportsService(
+ OUString const & ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+css::uno::Sequence< OUString >
+cppuhelper::ServiceManager::getSupportedServiceNames()
+{
+ return { "com.sun.star.lang.MultiServiceFactory", "com.sun.star.lang.ServiceManager" };
+}
+
+css::uno::Reference< css::uno::XInterface >
+cppuhelper::ServiceManager::createInstance(
+ OUString const & aServiceSpecifier)
+{
+ assert(context_.is());
+ return createInstanceWithContext(aServiceSpecifier, context_);
+}
+
+css::uno::Reference< css::uno::XInterface >
+cppuhelper::ServiceManager::createInstanceWithArguments(
+ OUString const & ServiceSpecifier,
+ css::uno::Sequence< css::uno::Any > const & Arguments)
+{
+ assert(context_.is());
+ return createInstanceWithArgumentsAndContext(
+ ServiceSpecifier, Arguments, context_);
+}
+
+css::uno::Sequence< OUString >
+cppuhelper::ServiceManager::getAvailableServiceNames()
+{
+ osl::MutexGuard g(rBHelper.rMutex);
+ if (isDisposed()) {
+ return css::uno::Sequence< OUString >();
+ }
+ if (data_.services.size() > o3tl::make_unsigned(SAL_MAX_INT32)) {
+ throw css::uno::RuntimeException(
+ "getAvailableServiceNames: too many services",
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ return comphelper::mapKeysToSequence(data_.services);
+}
+
+css::uno::Reference< css::uno::XInterface >
+cppuhelper::ServiceManager::createInstanceWithContext(
+ OUString const & aServiceSpecifier,
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+{
+ std::shared_ptr< Data::Implementation > impl(
+ findServiceImplementation(Context, aServiceSpecifier));
+ return impl == nullptr ? css::uno::Reference<css::uno::XInterface>()
+ : impl->createInstance(Context, false);
+}
+
+css::uno::Reference< css::uno::XInterface >
+cppuhelper::ServiceManager::createInstanceWithArgumentsAndContext(
+ OUString const & ServiceSpecifier,
+ css::uno::Sequence< css::uno::Any > const & Arguments,
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+{
+ std::shared_ptr< Data::Implementation > impl(
+ findServiceImplementation(Context, ServiceSpecifier));
+ return impl == nullptr ? css::uno::Reference<css::uno::XInterface>()
+ : impl->createInstanceWithArguments(Context, false, Arguments);
+}
+
+css::uno::Type cppuhelper::ServiceManager::getElementType()
+{
+ return css::uno::Type();
+}
+
+sal_Bool cppuhelper::ServiceManager::hasElements()
+{
+ osl::MutexGuard g(rBHelper.rMutex);
+ return
+ !(data_.namedImplementations.empty()
+ && data_.dynamicImplementations.empty());
+}
+
+css::uno::Reference< css::container::XEnumeration >
+cppuhelper::ServiceManager::createEnumeration()
+{
+ throw css::uno::RuntimeException(
+ "ServiceManager createEnumeration: method not supported",
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+sal_Bool cppuhelper::ServiceManager::has(css::uno::Any const &)
+{
+ throw css::uno::RuntimeException(
+ "ServiceManager has: method not supported",
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+void cppuhelper::ServiceManager::insert(css::uno::Any const & aElement)
+{
+ css::uno::Sequence< css::beans::NamedValue > args;
+ if (aElement >>= args) {
+ std::vector< OUString > uris;
+ css::uno::Reference< css::uno::XComponentContext > alienContext;
+ for (const auto & arg : std::as_const(args)) {
+ if (arg.Name == "uri") {
+ OUString uri;
+ if (!(arg.Value >>= uri)) {
+ throw css::lang::IllegalArgumentException(
+ "Bad uri argument",
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ uris.push_back(uri);
+ } else if (arg.Name == "component-context") {
+ if (alienContext.is()) {
+ throw css::lang::IllegalArgumentException(
+ "Multiple component-context arguments",
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ if (!(arg.Value >>= alienContext) || !alienContext.is()) {
+ throw css::lang::IllegalArgumentException(
+ "Bad component-context argument",
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ } else {
+ throw css::lang::IllegalArgumentException(
+ "Bad argument " + arg.Name,
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ }
+ insertRdbFiles(uris, alienContext);
+ return;
+ }
+ css::uno::Reference< css::lang::XServiceInfo > info;
+ if ((aElement >>= info) && info.is()) {
+ insertLegacyFactory(info);
+ return;
+ }
+
+ throw css::lang::IllegalArgumentException(
+ "Bad insert element", static_cast< cppu::OWeakObject * >(this), 0);
+}
+
+void cppuhelper::ServiceManager::remove(css::uno::Any const & aElement)
+{
+ css::uno::Sequence< css::beans::NamedValue > args;
+ if (aElement >>= args) {
+ std::vector< OUString > uris;
+ for (const auto & i : std::as_const(args)) {
+ if (i.Name != "uri") {
+ throw css::lang::IllegalArgumentException(
+ "Bad argument " + i.Name,
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ OUString uri;
+ if (!(i.Value >>= uri)) {
+ throw css::lang::IllegalArgumentException(
+ "Bad uri argument",
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ uris.push_back(uri);
+ }
+ removeRdbFiles(uris);
+ return;
+ }
+ css::uno::Reference< css::lang::XServiceInfo > info;
+ if ((aElement >>= info) && info.is()) {
+ if (!removeLegacyFactory(info, true)) {
+ throw css::container::NoSuchElementException(
+ "Remove non-inserted factory object",
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ return;
+ }
+ OUString impl;
+ if (aElement >>= impl) {
+ // For live-removal of extensions:
+ removeImplementation(impl);
+ return;
+ }
+ throw css::lang::IllegalArgumentException(
+ "Bad remove element", static_cast< cppu::OWeakObject * >(this), 0);
+}
+
+css::uno::Reference< css::container::XEnumeration >
+cppuhelper::ServiceManager::createContentEnumeration(
+ OUString const & aServiceName)
+{
+ std::vector< std::shared_ptr< Data::Implementation > > impls;
+ {
+ osl::MutexGuard g(rBHelper.rMutex);
+ Data::ImplementationMap::const_iterator i(
+ data_.services.find(aServiceName));
+ if (i != data_.services.end()) {
+ impls = i->second;
+ }
+ }
+ std::vector< css::uno::Any > factories;
+ for (const auto& rxImpl : impls)
+ {
+ Data::Implementation * impl = rxImpl.get();
+ assert(impl != nullptr);
+ {
+ osl::MutexGuard g(rBHelper.rMutex);
+ if (isDisposed()) {
+ factories.clear();
+ break;
+ }
+ if (impl->status == Data::Implementation::STATUS_NEW) {
+ // Postpone actual implementation instantiation as long as
+ // possible (so that e.g. opening LO's "Tools - Macros" menu
+ // does not try to instantiate a JVM, which can lead to a
+ // synchronous error dialog when no JVM is specified, and
+ // showing the dialog while hovering over a menu can cause
+ // trouble):
+ impl->factory1 = new ImplementationWrapper(this, rxImpl);
+ impl->status = Data::Implementation::STATUS_WRAPPER;
+ }
+ if (impl->constructorFn != nullptr && !impl->factory1.is()) {
+ impl->factory1 = new ImplementationWrapper(this, rxImpl);
+ }
+ }
+ if (impl->factory1.is()) {
+ factories.push_back(css::uno::Any(impl->factory1));
+ } else {
+ assert(impl->factory2.is());
+ factories.push_back(css::uno::Any(impl->factory2));
+ }
+ }
+ return new ContentEnumeration(std::move(factories));
+}
+
+css::uno::Reference< css::beans::XPropertySetInfo >
+cppuhelper::ServiceManager::getPropertySetInfo()
+{
+ return this;
+}
+
+void cppuhelper::ServiceManager::setPropertyValue(
+ OUString const & aPropertyName, css::uno::Any const &)
+{
+ if (aPropertyName == "DefaultContext") {
+ throw css::beans::PropertyVetoException(
+ aPropertyName, static_cast< cppu::OWeakObject * >(this));
+ } else {
+ throw css::beans::UnknownPropertyException(
+ aPropertyName, static_cast< cppu::OWeakObject * >(this));
+ }
+}
+
+css::uno::Any cppuhelper::ServiceManager::getPropertyValue(
+ OUString const & PropertyName)
+{
+ if (PropertyName != "DefaultContext") {
+ throw css::beans::UnknownPropertyException(
+ PropertyName, static_cast< cppu::OWeakObject * >(this));
+ }
+ assert(context_.is());
+ return css::uno::Any(context_);
+}
+
+void cppuhelper::ServiceManager::addPropertyChangeListener(
+ OUString const & aPropertyName,
+ css::uno::Reference< css::beans::XPropertyChangeListener > const &
+ xListener)
+{
+ if (!aPropertyName.isEmpty() && aPropertyName != "DefaultContext") {
+ throw css::beans::UnknownPropertyException(
+ aPropertyName, static_cast< cppu::OWeakObject * >(this));
+ }
+ // DefaultContext does not change, so just treat it as an event listener:
+ return addEventListener(xListener);
+}
+
+void cppuhelper::ServiceManager::removePropertyChangeListener(
+ OUString const & aPropertyName,
+ css::uno::Reference< css::beans::XPropertyChangeListener > const &
+ aListener)
+{
+ if (!aPropertyName.isEmpty() && aPropertyName != "DefaultContext") {
+ throw css::beans::UnknownPropertyException(
+ aPropertyName, static_cast< cppu::OWeakObject * >(this));
+ }
+ // DefaultContext does not change, so just treat it as an event listener:
+ return removeEventListener(aListener);
+}
+
+void cppuhelper::ServiceManager::addVetoableChangeListener(
+ OUString const & PropertyName,
+ css::uno::Reference< css::beans::XVetoableChangeListener > const &
+ aListener)
+{
+ if (!PropertyName.isEmpty() && PropertyName != "DefaultContext") {
+ throw css::beans::UnknownPropertyException(
+ PropertyName, static_cast< cppu::OWeakObject * >(this));
+ }
+ // DefaultContext does not change, so just treat it as an event listener:
+ return addEventListener(aListener);
+}
+
+void cppuhelper::ServiceManager::removeVetoableChangeListener(
+ OUString const & PropertyName,
+ css::uno::Reference< css::beans::XVetoableChangeListener > const &
+ aListener)
+{
+ if (!PropertyName.isEmpty() && PropertyName != "DefaultContext") {
+ throw css::beans::UnknownPropertyException(
+ PropertyName, static_cast< cppu::OWeakObject * >(this));
+ }
+ // DefaultContext does not change, so just treat it as an event listener:
+ return removeEventListener(aListener);
+}
+
+css::uno::Sequence< css::beans::Property >
+cppuhelper::ServiceManager::getProperties() {
+ return { getDefaultContextProperty() };
+}
+
+css::beans::Property cppuhelper::ServiceManager::getPropertyByName(
+ OUString const & aName)
+{
+ if (aName != "DefaultContext") {
+ throw css::beans::UnknownPropertyException(
+ aName, static_cast< cppu::OWeakObject * >(this));
+ }
+ return getDefaultContextProperty();
+}
+
+sal_Bool cppuhelper::ServiceManager::hasPropertyByName(
+ OUString const & Name)
+{
+ return Name == "DefaultContext";
+}
+
+cppuhelper::ServiceManager::~ServiceManager() {}
+
+void cppuhelper::ServiceManager::disposing(
+ css::lang::EventObject const & Source)
+{
+ removeLegacyFactory(
+ css::uno::Reference< css::lang::XServiceInfo >(
+ Source.Source, css::uno::UNO_QUERY_THROW),
+ false);
+}
+
+void cppuhelper::ServiceManager::removeEventListenerFromComponent(
+ css::uno::Reference< css::lang::XComponent > const & component)
+{
+ assert(component.is());
+ try {
+ component->removeEventListener(this);
+ } catch (css::uno::RuntimeException & e) {
+ SAL_INFO(
+ "cppuhelper",
+ "Ignored removeEventListener RuntimeException " + e.Message);
+ }
+}
+
+void cppuhelper::ServiceManager::init(std::u16string_view rdbUris) {
+ for (sal_Int32 i = 0; i != -1;) {
+ std::u16string_view uri(o3tl::getToken(rdbUris, 0, ' ', i));
+ if (uri.empty()) {
+ continue;
+ }
+ bool optional;
+ bool directory;
+ cppu::decodeRdbUri(&uri, &optional, &directory);
+ if (directory) {
+ readRdbDirectory(uri, optional);
+ } else {
+ readRdbFile(OUString(uri), optional);
+ }
+ }
+}
+
+void cppuhelper::ServiceManager::readRdbDirectory(
+ std::u16string_view uri, bool optional)
+{
+ osl::Directory dir = OUString(uri);
+ switch (dir.open()) {
+ case osl::FileBase::E_None:
+ break;
+ case osl::FileBase::E_NOENT:
+ if (optional) {
+ SAL_INFO("cppuhelper", "Ignored optional " << OUString(uri));
+ return;
+ }
+ [[fallthrough]];
+ default:
+ throw css::uno::DeploymentException(
+ OUString::Concat("Cannot open directory ") + uri,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ for (;;) {
+ OUString url;
+ if (!cppu::nextDirectoryItem(dir, &url)) {
+ break;
+ }
+ readRdbFile(url, false);
+ }
+}
+
+void cppuhelper::ServiceManager::readRdbFile(
+ OUString const & uri, bool optional)
+{
+ try {
+ Parser(
+ uri, css::uno::Reference< css::uno::XComponentContext >(), &data_);
+ } catch (css::container::NoSuchElementException &) {
+ if (!optional) {
+ throw css::uno::DeploymentException(
+ uri + ": no such file",
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ SAL_INFO("cppuhelper", "Ignored optional " << uri);
+ } catch (css::registry::InvalidRegistryException & e) {
+ if (!readLegacyRdbFile(uri)) {
+ throw css::uno::DeploymentException(
+ "InvalidRegistryException: " + e.Message,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ } catch (css::uno::RuntimeException &) {
+ if (!readLegacyRdbFile(uri)) {
+ throw;
+ }
+ }
+}
+
+bool cppuhelper::ServiceManager::readLegacyRdbFile(OUString const & uri) {
+ Registry reg;
+ switch (reg.open(uri, RegAccessMode::READONLY)) {
+ case RegError::NO_ERROR:
+ break;
+ case RegError::REGISTRY_NOT_EXISTS:
+ case RegError::INVALID_REGISTRY:
+ {
+ // Ignore empty rdb files (which are at least seen by subordinate
+ // uno processes during extension registration; Registry::open can
+ // fail on them if mmap(2) returns EINVAL for a zero length):
+ osl::DirectoryItem item;
+ if (osl::DirectoryItem::get(uri, item) == osl::FileBase::E_None) {
+ osl::FileStatus status(osl_FileStatus_Mask_FileSize);
+ if (item.getFileStatus(status) == osl::FileBase::E_None
+ && status.getFileSize() == 0)
+ {
+ return true;
+ }
+ }
+ }
+ [[fallthrough]];
+ default:
+ return false;
+ }
+ RegistryKey rootKey;
+ if (reg.openRootKey(rootKey) != RegError::NO_ERROR) {
+ throw css::uno::DeploymentException(
+ "Failure reading legacy rdb file " + uri,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ RegistryKeyArray impls;
+ switch (rootKey.openSubKeys("IMPLEMENTATIONS", impls)) {
+ case RegError::NO_ERROR:
+ break;
+ case RegError::KEY_NOT_EXISTS:
+ return true;
+ default:
+ throw css::uno::DeploymentException(
+ "Failure reading legacy rdb file " + uri,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ for (sal_uInt32 i = 0; i != impls.getLength(); ++i) {
+ RegistryKey implKey(impls.getElement(i));
+ assert(implKey.getName().match("/IMPLEMENTATIONS/"));
+ OUString name(
+ implKey.getName().copy(RTL_CONSTASCII_LENGTH("/IMPLEMENTATIONS/")));
+ std::shared_ptr< Data::Implementation > impl =
+ std::make_shared<Data::Implementation>(
+ name, readLegacyRdbString(uri, implKey, "UNO/ACTIVATOR"),
+ readLegacyRdbString(uri, implKey, "UNO/LOCATION"), "", "", "", false,
+ css::uno::Reference< css::uno::XComponentContext >(), uri);
+ if (!data_.namedImplementations.emplace(name, impl).second)
+ {
+ throw css::registry::InvalidRegistryException(
+ uri + ": duplicate <implementation name=\"" + name + "\">");
+ }
+ readLegacyRdbStrings(
+ uri, implKey, "UNO/SERVICES", &impl->services);
+ for (const auto& rService : impl->services)
+ {
+ data_.services[rService].push_back(impl);
+ }
+ readLegacyRdbStrings(
+ uri, implKey, "UNO/SINGLETONS", &impl->singletons);
+ for (const auto& rSingleton : impl->singletons)
+ {
+ data_.singletons[rSingleton].push_back(impl);
+ }
+ }
+ return true;
+}
+
+OUString cppuhelper::ServiceManager::readLegacyRdbString(
+ std::u16string_view uri, RegistryKey & key, OUString const & path)
+{
+ RegistryKey subkey;
+ RegValueType t;
+ sal_uInt32 s(0);
+ if (key.openKey(path, subkey) != RegError::NO_ERROR
+ || subkey.getValueInfo(OUString(), &t, &s) != RegError::NO_ERROR
+ || t != RegValueType::STRING
+ || s == 0 || s > o3tl::make_unsigned(SAL_MAX_INT32))
+ {
+ throw css::uno::DeploymentException(
+ OUString::Concat("Failure reading legacy rdb file ") + uri,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ OUString val;
+ std::vector< char > v(s); // assuming sal_uInt32 fits into vector::size_type
+ if (subkey.getValue(OUString(), v.data()) != RegError::NO_ERROR
+ || v.back() != '\0'
+ || !rtl_convertStringToUString(
+ &val.pData, v.data(), static_cast< sal_Int32 >(s - 1),
+ RTL_TEXTENCODING_UTF8,
+ (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
+ | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
+ | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
+ {
+ throw css::uno::DeploymentException(
+ OUString::Concat("Failure reading legacy rdb file ") + uri,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ return val;
+}
+
+void cppuhelper::ServiceManager::readLegacyRdbStrings(
+ std::u16string_view uri, RegistryKey & key, OUString const & path,
+ std::vector< OUString > * strings)
+{
+ assert(strings != nullptr);
+ RegistryKey subkey;
+ switch (key.openKey(path, subkey)) {
+ case RegError::NO_ERROR:
+ break;
+ case RegError::KEY_NOT_EXISTS:
+ return;
+ default:
+ throw css::uno::DeploymentException(
+ OUString::Concat("Failure reading legacy rdb file ") + uri,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ OUString prefix(subkey.getName() + "/");
+ RegistryKeyNames names;
+ if (subkey.getKeyNames(OUString(), names) != RegError::NO_ERROR) {
+ throw css::uno::DeploymentException(
+ OUString::Concat("Failure reading legacy rdb file ") + uri,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ for (sal_uInt32 i = 0; i != names.getLength(); ++i) {
+ assert(names.getElement(i).match(prefix));
+ strings->push_back(names.getElement(i).copy(prefix.getLength()));
+ }
+}
+
+void cppuhelper::ServiceManager::insertRdbFiles(
+ std::vector< OUString > const & uris,
+ css::uno::Reference< css::uno::XComponentContext > const & alienContext)
+{
+ Data extra;
+ for (const auto& rUri : uris)
+ {
+ try {
+ Parser(rUri, alienContext, &extra);
+ } catch (css::container::NoSuchElementException &) {
+ throw css::lang::IllegalArgumentException(
+ rUri + ": no such file", static_cast< cppu::OWeakObject * >(this),
+ 0);
+ } catch (css::registry::InvalidRegistryException & e) {
+ throw css::lang::IllegalArgumentException(
+ "InvalidRegistryException: " + e.Message,
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ }
+ insertExtraData(extra);
+}
+
+void cppuhelper::ServiceManager::insertLegacyFactory(
+ css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo)
+{
+ assert(factoryInfo.is());
+ OUString name(factoryInfo->getImplementationName());
+ css::uno::Reference< css::lang::XSingleComponentFactory > f1(
+ factoryInfo, css::uno::UNO_QUERY);
+ css::uno::Reference< css::lang::XSingleServiceFactory > f2;
+ if (!f1.is()) {
+ f2.set(factoryInfo, css::uno::UNO_QUERY);
+ if (!f2.is()) {
+ throw css::lang::IllegalArgumentException(
+ ("Bad XServiceInfo argument implements neither"
+ " XSingleComponentFactory nor XSingleServiceFactory"),
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ }
+ css::uno::Reference< css::lang::XComponent > comp(
+ factoryInfo, css::uno::UNO_QUERY);
+ std::shared_ptr< Data::Implementation > impl =
+ std::make_shared<Data::Implementation>(name, f1, f2, comp);
+ Data extra;
+ if (!name.isEmpty()) {
+ extra.namedImplementations.emplace(name, impl);
+ }
+ extra.dynamicImplementations.emplace(factoryInfo, impl);
+ const css::uno::Sequence< OUString > services(
+ factoryInfo->getSupportedServiceNames());
+ for (const auto & i : services) {
+ impl->services.push_back(i);
+ extra.services[i].push_back(impl);
+ }
+ if (insertExtraData(extra) && comp.is()) {
+ comp->addEventListener(this);
+ }
+}
+
+bool cppuhelper::ServiceManager::insertExtraData(Data const & extra) {
+ {
+ osl::MutexGuard g(rBHelper.rMutex);
+ if (isDisposed()) {
+ return false;
+ }
+ auto i = std::find_if(extra.namedImplementations.begin(), extra.namedImplementations.end(),
+ [this](const Data::NamedImplementations::value_type& rEntry) {
+ return data_.namedImplementations.find(rEntry.first) != data_.namedImplementations.end(); });
+ if (i != extra.namedImplementations.end())
+ {
+ throw css::lang::IllegalArgumentException(
+ "Insert duplicate implementation name " + i->first,
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ bool bDuplicate = std::any_of(extra.dynamicImplementations.begin(), extra.dynamicImplementations.end(),
+ [this](const Data::DynamicImplementations::value_type& rEntry) {
+ return data_.dynamicImplementations.find(rEntry.first) != data_.dynamicImplementations.end(); });
+ if (bDuplicate)
+ {
+ throw css::lang::IllegalArgumentException(
+ "Insert duplicate factory object",
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ //TODO: The below leaves data_ in an inconsistent state upon exceptions:
+ data_.namedImplementations.insert(
+ extra.namedImplementations.begin(),
+ extra.namedImplementations.end());
+ data_.dynamicImplementations.insert(
+ extra.dynamicImplementations.begin(),
+ extra.dynamicImplementations.end());
+ insertImplementationMap(&data_.services, extra.services);
+ insertImplementationMap(&data_.singletons, extra.singletons);
+ }
+ //TODO: Updating the component context singleton data should be part of the
+ // atomic service manager update:
+ if (extra.singletons.empty())
+ return true;
+
+ assert(context_.is());
+ css::uno::Reference< css::container::XNameContainer > cont(
+ context_, css::uno::UNO_QUERY_THROW);
+ for (const auto& [rName, rImpls] : extra.singletons)
+ {
+ OUString name("/singletons/" + rName);
+ //TODO: Update should be atomic:
+ try {
+ cont->removeByName(name + "/arguments");
+ } catch (const css::container::NoSuchElementException &) {}
+ assert(!rImpls.empty());
+ assert(rImpls[0]);
+ SAL_INFO_IF(
+ rImpls.size() > 1, "cppuhelper",
+ "Arbitrarily choosing " << rImpls[0]->name
+ << " among multiple implementations for singleton "
+ << rName);
+ try {
+ cont->insertByName(
+ name + "/service", css::uno::Any(rImpls[0]->name));
+ } catch (css::container::ElementExistException &) {
+ cont->replaceByName(
+ name + "/service", css::uno::Any(rImpls[0]->name));
+ }
+ try {
+ cont->insertByName(name, css::uno::Any());
+ } catch (css::container::ElementExistException &) {
+ SAL_INFO("cppuhelper", "Overwriting singleton " << rName);
+ cont->replaceByName(name, css::uno::Any());
+ }
+ }
+ return true;
+}
+
+void cppuhelper::ServiceManager::removeRdbFiles(
+ std::vector< OUString > const & uris)
+{
+ // The underlying data structures make this function somewhat inefficient,
+ // but the assumption is that it is rarely called (and that if it is called,
+ // it is called with a uris vector of size one):
+ std::vector< std::shared_ptr< Data::Implementation > > clear;
+ {
+ osl::MutexGuard g(rBHelper.rMutex);
+ for (const auto& rUri : uris)
+ {
+ for (Data::NamedImplementations::iterator j(
+ data_.namedImplementations.begin());
+ j != data_.namedImplementations.end();)
+ {
+ assert(j->second);
+ if (j->second->rdbFile == rUri) {
+ clear.push_back(j->second);
+ //TODO: The below leaves data_ in an inconsistent state upon
+ // exceptions:
+ removeFromImplementationMap(
+ &data_.services, j->second->services, j->second);
+ removeFromImplementationMap(
+ &data_.singletons, j->second->singletons,
+ j->second);
+ j = data_.namedImplementations.erase(j);
+ } else {
+ ++j;
+ }
+ }
+ }
+ }
+ //TODO: Update the component context singleton data
+}
+
+bool cppuhelper::ServiceManager::removeLegacyFactory(
+ css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo,
+ bool removeListener)
+{
+ assert(factoryInfo.is());
+ std::shared_ptr< Data::Implementation > clear;
+ css::uno::Reference< css::lang::XComponent > comp;
+ {
+ osl::MutexGuard g(rBHelper.rMutex);
+ Data::DynamicImplementations::iterator i(
+ data_.dynamicImplementations.find(factoryInfo));
+ if (i == data_.dynamicImplementations.end()) {
+ return isDisposed();
+ }
+ assert(i->second);
+ clear = i->second;
+ if (removeListener) {
+ comp = i->second->component;
+ }
+ //TODO: The below leaves data_ in an inconsistent state upon exceptions:
+ removeFromImplementationMap(
+ &data_.services, i->second->services, i->second);
+ removeFromImplementationMap(
+ &data_.singletons, i->second->singletons, i->second);
+ if (!i->second->name.isEmpty()) {
+ data_.namedImplementations.erase(i->second->name);
+ }
+ data_.dynamicImplementations.erase(i);
+ }
+ if (comp.is()) {
+ removeEventListenerFromComponent(comp);
+ }
+ return true;
+}
+
+void cppuhelper::ServiceManager::removeImplementation(const OUString & name) {
+ // The underlying data structures make this function somewhat inefficient,
+ // but the assumption is that it is rarely called:
+ std::shared_ptr< Data::Implementation > clear;
+ {
+ osl::MutexGuard g(rBHelper.rMutex);
+ if (isDisposed()) {
+ return;
+ }
+ Data::NamedImplementations::iterator i(
+ data_.namedImplementations.find(name));
+ if (i == data_.namedImplementations.end()) {
+ throw css::container::NoSuchElementException(
+ "Remove non-inserted implementation " + name,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ assert(i->second);
+ clear = i->second;
+ //TODO: The below leaves data_ in an inconsistent state upon exceptions:
+ removeFromImplementationMap(
+ &data_.services, i->second->services, i->second);
+ removeFromImplementationMap(
+ &data_.singletons, i->second->singletons, i->second);
+ auto j = std::find_if(data_.dynamicImplementations.begin(), data_.dynamicImplementations.end(),
+ [&i](const Data::DynamicImplementations::value_type& rEntry) { return rEntry.second == i->second; });
+ if (j != data_.dynamicImplementations.end())
+ data_.dynamicImplementations.erase(j);
+ data_.namedImplementations.erase(i);
+ }
+}
+
+std::shared_ptr< cppuhelper::ServiceManager::Data::Implementation >
+cppuhelper::ServiceManager::findServiceImplementation(
+ css::uno::Reference< css::uno::XComponentContext > const & context,
+ OUString const & specifier)
+{
+ std::shared_ptr< Data::Implementation > impl;
+ bool loaded;
+ {
+ osl::MutexGuard g(rBHelper.rMutex);
+ Data::ImplementationMap::const_iterator i(
+ data_.services.find(specifier));
+ if (i == data_.services.end()) {
+ Data::NamedImplementations::const_iterator j(
+ data_.namedImplementations.find(specifier));
+ if (j == data_.namedImplementations.end()) {
+ SAL_INFO("cppuhelper", "No implementation for " << specifier);
+ return std::shared_ptr< Data::Implementation >();
+ }
+ impl = j->second;
+ } else {
+ assert(!i->second.empty());
+ SAL_INFO_IF(
+ i->second.size() > 1, "cppuhelper",
+ "Arbitrarily choosing " << i->second[0]->name
+ << " among multiple implementations for " << i->first);
+ impl = i->second[0];
+ }
+ assert(impl);
+ loaded = impl->status == Data::Implementation::STATUS_LOADED;
+ }
+ if (!loaded) {
+ loadImplementation(context, impl);
+ }
+ return impl;
+}
+
+/// Make a simpler unique name for preload / progress reporting.
+#ifndef DISABLE_DYNLOADING
+static OUString simplifyModule(std::u16string_view uri)
+{
+ sal_Int32 nIdx;
+ OUStringBuffer edit(uri);
+ if ((nIdx = edit.lastIndexOf('/')) > 0)
+ edit.remove(0,nIdx+1);
+ if ((nIdx = edit.lastIndexOf(':')) > 0)
+ edit.remove(0,nIdx+1);
+ if ((nIdx = edit.lastIndexOf("lo.so")) > 0)
+ edit.truncate(nIdx);
+ if ((nIdx = edit.lastIndexOf(".3")) > 0)
+ edit.truncate(nIdx);
+ if ((nIdx = edit.lastIndexOf("gcc3.so")) > 0)
+ edit.truncate(nIdx);
+ if ((nIdx = edit.lastIndexOf(".so")) > 0)
+ edit.truncate(nIdx);
+ if ((nIdx = edit.lastIndexOf("_uno")) > 0)
+ edit.truncate(nIdx);
+ if ((nIdx = edit.lastIndexOf(".jar")) > 0)
+ edit.truncate(nIdx);
+ if (edit.indexOf("lib") == 0)
+ edit.remove(0,3);
+ return edit.makeStringAndClear();
+}
+#endif
+
+/// Used only by LibreOfficeKit when used by Online to pre-initialize
+void cppuhelper::ServiceManager::preloadImplementations() {
+#ifdef DISABLE_DYNLOADING
+ abort();
+#else
+ OUString aUri;
+ osl::MutexGuard g(rBHelper.rMutex);
+ css::uno::Environment aSourceEnv(css::uno::Environment::getCurrent());
+
+ std::cerr << "preload:";
+ std::vector<OUString> aReported;
+ std::vector<OUString> aDisabled;
+ OUStringBuffer aDisabledMsg;
+ OUStringBuffer aMissingMsg;
+
+ /// Allow external callers & testers to disable certain components
+ const char *pDisable = getenv("UNODISABLELIBRARY");
+ if (pDisable)
+ {
+ OUString aDisable(pDisable, strlen(pDisable), RTL_TEXTENCODING_UTF8);
+ for (sal_Int32 i = 0; i >= 0; )
+ {
+ OUString tok( aDisable.getToken(0, ' ', i) );
+ tok = tok.trim();
+ if (!tok.isEmpty())
+ aDisabled.push_back(tok);
+ }
+ }
+
+ // loop all implementations
+ for (const auto& rEntry : data_.namedImplementations)
+ {
+ if (rEntry.second->loader != "com.sun.star.loader.SharedLibrary" ||
+ rEntry.second->status == Data::Implementation::STATUS_LOADED)
+ continue;
+
+ OUString simplified;
+ try
+ {
+ const OUString &aLibrary = rEntry.second->uri;
+
+ if (aLibrary.isEmpty())
+ continue;
+
+ simplified = simplifyModule(aLibrary);
+
+ bool bDisabled =
+ std::find(aDisabled.begin(), aDisabled.end(), simplified) != aDisabled.end();
+
+ if (std::find(aReported.begin(), aReported.end(), aLibrary) == aReported.end())
+ {
+ if (bDisabled)
+ {
+ aDisabledMsg.append(simplified);
+ aDisabledMsg.append(" ");
+ }
+ else
+ {
+ std::cerr << " " << simplified;
+ std::cerr.flush();
+ }
+ aReported.push_back(aLibrary);
+ }
+
+ if (bDisabled)
+ continue;
+
+ // expand absolute URI implementation component library
+ aUri = cppu::bootstrap_expandUri(aLibrary);
+ }
+ catch (css::lang::IllegalArgumentException& aError)
+ {
+ throw css::uno::DeploymentException(
+ "Cannot expand URI" + rEntry.second->uri + ": " + aError.Message,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+
+ // load component library
+ osl::Module aModule(aUri, SAL_LOADMODULE_NOW | SAL_LOADMODULE_GLOBAL);
+
+ if (!aModule.is())
+ {
+ aMissingMsg.append(simplified);
+ aMissingMsg.append(" ");
+ }
+
+ if (aModule.is() &&
+ !rEntry.second->environment.isEmpty())
+ {
+ oslGenericFunction fpFactory;
+ css::uno::Environment aTargetEnv;
+ css::uno::Reference<css::uno::XInterface> xFactory;
+
+ if(rEntry.second->constructorName.isEmpty())
+ {
+ OUString aSymFactory;
+ // expand full name component factory symbol
+ if (rEntry.second->prefix == "direct")
+ aSymFactory = rEntry.second->name.replace('.', '_') + "_" COMPONENT_GETFACTORY;
+ else if (!rEntry.second->prefix.isEmpty())
+ aSymFactory = rEntry.second->prefix + "_" COMPONENT_GETFACTORY;
+ else
+ aSymFactory = COMPONENT_GETFACTORY;
+
+ // get function symbol component factory
+ fpFactory = aModule.getFunctionSymbol(aSymFactory);
+ if (fpFactory == nullptr)
+ {
+ throw css::loader::CannotActivateFactoryException(
+ ("no factory symbol \"" + aSymFactory + "\" in component library :" + aUri),
+ css::uno::Reference<css::uno::XInterface>());
+ }
+
+ aTargetEnv = cppuhelper::detail::getEnvironment(rEntry.second->environment, rEntry.second->name);
+ component_getFactoryFunc fpComponentFactory = reinterpret_cast<component_getFactoryFunc>(fpFactory);
+
+ if (aSourceEnv.get() == aTargetEnv.get())
+ {
+ // invoke function component factory
+ OString aImpl(OUStringToOString(rEntry.second->name, RTL_TEXTENCODING_ASCII_US));
+ xFactory.set(css::uno::Reference<css::uno::XInterface>(static_cast<css::uno::XInterface *>(
+ (*fpComponentFactory)(aImpl.getStr(), this, nullptr)), SAL_NO_ACQUIRE));
+ }
+ }
+ else
+ {
+ // get function symbol component factory
+ aTargetEnv = cppuhelper::detail::getEnvironment(rEntry.second->environment, rEntry.second->name);
+ fpFactory = (aSourceEnv.get() == aTargetEnv.get()) ?
+ aModule.getFunctionSymbol(rEntry.second->constructorName) : nullptr;
+ }
+
+ css::uno::Reference<css::lang::XSingleComponentFactory> xSCFactory;
+ css::uno::Reference<css::lang::XSingleServiceFactory> xSSFactory;
+
+ // query interface XSingleComponentFactory or XSingleServiceFactory
+ if (xFactory.is())
+ {
+ xSCFactory.set(xFactory, css::uno::UNO_QUERY);
+ if (!xSCFactory.is())
+ {
+ xSSFactory.set(xFactory, css::uno::UNO_QUERY);
+ if (!xSSFactory.is())
+ throw css::uno::DeploymentException(
+ ("Implementation " + rEntry.second->name
+ + " does not provide a constructor or factory"),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ }
+
+ if (!rEntry.second->constructorName.isEmpty() && fpFactory)
+ rEntry.second->constructorFn = WrapperConstructorFn(reinterpret_cast<ImplementationConstructorFn *>(fpFactory));
+
+ rEntry.second->factory1 = xSCFactory;
+ rEntry.second->factory2 = xSSFactory;
+ rEntry.second->status = Data::Implementation::STATUS_LOADED;
+
+ }
+
+ // Some libraries use other (non-UNO) libraries requiring preinit
+ oslGenericFunction fpPreload = aModule.getFunctionSymbol( "lok_preload_hook" );
+ if (fpPreload)
+ {
+ static std::vector<oslGenericFunction> aPreloaded;
+ if (std::find(aPreloaded.begin(), aPreloaded.end(), fpPreload) == aPreloaded.end())
+ {
+ aPreloaded.push_back(fpPreload);
+ fpPreload();
+ }
+ }
+
+ // leak aModule
+ aModule.release();
+ }
+ std::cerr << std::endl;
+
+ if (aMissingMsg.getLength() > 0)
+ {
+ OUString aMsg = aMissingMsg.makeStringAndClear();
+ std::cerr << "Absent (often optional): " << aMsg << "\n";
+ }
+ if (aDisabledMsg.getLength() > 0)
+ {
+ OUString aMsg = aDisabledMsg.makeStringAndClear();
+ std::cerr << "Disabled: " << aMsg << "\n";
+ }
+ std::cerr.flush();
+
+ // Various rather important uno mappings.
+ static struct {
+ const char *mpFrom;
+ const char *mpTo;
+ const char *mpPurpose;
+ } const aMappingLoad[] = {
+ { "gcc3", "uno", "" },
+ { "uno", "gcc3", "" },
+ };
+
+ static std::vector<css::uno::Mapping> maMaps;
+ for (auto &it : aMappingLoad)
+ {
+ maMaps.push_back(css::uno::Mapping(
+ OUString::createFromAscii(it.mpFrom),
+ OUString::createFromAscii(it.mpTo),
+ OUString::createFromAscii(it.mpPurpose)));
+ }
+#endif
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/servicemanager.hxx b/cppuhelper/source/servicemanager.hxx
new file mode 100644
index 000000000..cdf23b277
--- /dev/null
+++ b/cppuhelper/source/servicemanager.hxx
@@ -0,0 +1,361 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <cassert>
+#include <unordered_map>
+#include <memory>
+#include <mutex>
+#include <string_view>
+#include <utility>
+#include <vector>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/container/XContentEnumerationAccess.hpp>
+#include <com/sun/star/container/XSet.hpp>
+#include <com/sun/star/lang/XEventListener.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XMultiComponentFactory.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <rtl/ustring.hxx>
+
+namespace com::sun::star::lang {
+ class XSingleComponentFactory;
+}
+namespace cppu { struct ContextEntry_Init; }
+namespace com :: sun :: star :: lang { class XSingleServiceFactory; }
+namespace com :: sun :: star :: uno { class XComponentContext; }
+
+class RegistryKey;
+
+namespace cppuhelper {
+
+extern "C" {
+
+typedef css::uno::XInterface * ImplementationConstructorFn(
+ css::uno::XComponentContext *, css::uno::Sequence<css::uno::Any> const &);
+
+}
+
+typedef std::function<css::uno::XInterface * (css::uno::XComponentContext *, css::uno::Sequence<css::uno::Any> const&)> WrapperConstructorFn;
+
+typedef cppu::WeakComponentImplHelper<
+ css::lang::XServiceInfo, css::lang::XMultiServiceFactory,
+ css::lang::XMultiComponentFactory, css::container::XSet,
+ css::container::XContentEnumerationAccess, css::beans::XPropertySet,
+ css::beans::XPropertySetInfo, css::lang::XEventListener,
+ css::lang::XInitialization>
+ServiceManagerBase;
+
+class ServiceManager:
+ private cppu::BaseMutex, public ServiceManagerBase
+{
+public:
+ struct Data {
+ Data() = default;
+ Data(const Data&) = delete;
+ const Data& operator=(const Data&) = delete;
+
+ struct Implementation {
+ Implementation(
+ OUString theName, OUString theLoader,
+ OUString theUri, OUString theEnvironment,
+ OUString theConstructorName,
+ OUString thePrefix,
+ bool theIsSingleInstance,
+ css::uno::Reference< css::uno::XComponentContext > theAlienContext,
+ OUString theRdbFile):
+ name(std::move(theName)), loader(std::move(theLoader)), uri(std::move(theUri)), environment(std::move(theEnvironment)),
+ constructorName(std::move(theConstructorName)), prefix(std::move(thePrefix)),
+ isSingleInstance(theIsSingleInstance),
+ alienContext(std::move(theAlienContext)), rdbFile(std::move(theRdbFile)),
+ constructorFn(nullptr), status(STATUS_NEW), dispose(true)
+ {}
+
+ Implementation(
+ OUString theName,
+ css::uno::Reference< css::lang::XSingleComponentFactory >
+ const & theFactory1,
+ css::uno::Reference< css::lang::XSingleServiceFactory > const &
+ theFactory2,
+ css::uno::Reference< css::lang::XComponent > theComponent):
+ name(std::move(theName)), isSingleInstance(false), constructorFn(nullptr),
+ factory1(theFactory1), factory2(theFactory2),
+ component(std::move(theComponent)), status(STATUS_LOADED), dispose(true)
+ { assert(theFactory1.is() || theFactory2.is()); }
+
+ Implementation(const Implementation&) = delete;
+ const Implementation& operator=(const Implementation&) = delete;
+
+ css::uno::Reference<css::uno::XInterface> createInstance(
+ css::uno::Reference<css::uno::XComponentContext> const &
+ context,
+ bool singletonRequest);
+
+ css::uno::Reference<css::uno::XInterface>
+ createInstanceWithArguments(
+ css::uno::Reference<css::uno::XComponentContext> const &
+ context,
+ bool singletonRequest,
+ css::uno::Sequence<css::uno::Any> const & arguments);
+
+ bool shallDispose() const { return isSingleInstance || !singletons.empty(); }
+
+ enum Status { STATUS_NEW, STATUS_WRAPPER, STATUS_LOADED };
+
+ // Logically, exactly one of constructorFn, factory1, factory2 should
+ // be set. However, there are two exceptions: For one, when
+ // constructorFn is set, ServiceManager::createContentEnumeration will
+ // store the necessary ImplementationWrapper in factory1 (so that
+ // multiple calls to createContentEnumeration will return the same
+ // wrapper). For another, when factory1 should be set but status is
+ // STATUS_NEW, factory1 is not yet set (and when status is
+ // STATUS_WRAPPER, factory1 is merely set to an
+ // ImplementationWrapper---also due to a
+ // ServiceManager::createContentEnumeration call---and will be
+ // loaded later).
+ OUString name;
+ OUString loader;
+ OUString uri;
+ OUString environment;
+ OUString constructorName;
+ OUString prefix;
+ bool isSingleInstance;
+ css::uno::Reference< css::uno::XComponentContext > alienContext;
+ OUString rdbFile;
+ std::vector< OUString > services;
+ std::vector< OUString > singletons;
+ WrapperConstructorFn constructorFn;
+ css::uno::Reference< css::lang::XSingleComponentFactory > factory1;
+ css::uno::Reference< css::lang::XSingleServiceFactory > factory2;
+ css::uno::Reference< css::lang::XComponent > component;
+ Status status;
+
+ std::mutex mutex;
+ css::uno::Reference<css::uno::XInterface> singleInstance;
+ css::uno::Reference< css::lang::XComponent > disposeInstance;
+ bool dispose;
+
+ private:
+ css::uno::Reference<css::uno::XInterface> doCreateInstance(
+ css::uno::Reference<css::uno::XComponentContext> const & context);
+
+ css::uno::Reference<css::uno::XInterface> doCreateInstanceWithArguments(
+ css::uno::Reference<css::uno::XComponentContext> const & context,
+ css::uno::Sequence<css::uno::Any> const & arguments);
+
+ void updateDisposeInstance(
+ bool singletonRequest,
+ css::uno::Reference<css::uno::XInterface> const & instance);
+ };
+
+ typedef std::unordered_map< OUString, std::shared_ptr< Implementation > >
+ NamedImplementations;
+
+ typedef
+ std::unordered_map<
+ css::uno::Reference< css::lang::XServiceInfo >,
+ std::shared_ptr< Implementation > >
+ DynamicImplementations;
+
+ typedef
+ std::unordered_map<
+ OUString,
+ std::vector< std::shared_ptr< Implementation > > >
+ ImplementationMap;
+
+ NamedImplementations namedImplementations;
+ DynamicImplementations dynamicImplementations;
+ ImplementationMap services;
+ ImplementationMap singletons;
+ };
+
+ ServiceManager(): ServiceManagerBase(m_aMutex) {}
+
+ ServiceManager(const ServiceManager&) = delete;
+ const ServiceManager& operator=(const ServiceManager&) = delete;
+
+ using ServiceManagerBase::acquire;
+ using ServiceManagerBase::release;
+
+ void init(std::u16string_view rdbUris);
+
+ void setContext(
+ css::uno::Reference< css::uno::XComponentContext > const & context)
+ {
+ assert(context.is());
+ assert(!context_.is());
+ context_ = context;
+ }
+
+ void addSingletonContextEntries(
+ std::vector< cppu::ContextEntry_Init > * entries);
+
+ css::uno::Reference< css::uno::XComponentContext > const & getContext()
+ const
+ {
+ assert(context_.is());
+ return context_;
+ }
+
+ void loadImplementation(
+ css::uno::Reference< css::uno::XComponentContext > const & context,
+ std::shared_ptr< Data::Implementation > const & implementation);
+
+private:
+ virtual ~ServiceManager() override;
+
+ virtual void SAL_CALL disposing() override;
+
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedServiceNames() override;
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(
+ OUString const & aServiceSpecifier) override;
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithArguments(
+ OUString const & ServiceSpecifier,
+ css::uno::Sequence< css::uno::Any > const & Arguments) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getAvailableServiceNames() override;
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithContext(
+ OUString const & aServiceSpecifier,
+ css::uno::Reference< css::uno::XComponentContext > const & Context) override;
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithArgumentsAndContext(
+ OUString const & ServiceSpecifier,
+ css::uno::Sequence< css::uno::Any > const & Arguments,
+ css::uno::Reference< css::uno::XComponentContext > const & Context) override;
+
+ virtual css::uno::Type SAL_CALL getElementType() override;
+
+ virtual sal_Bool SAL_CALL hasElements() override;
+
+ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL
+ createEnumeration() override;
+
+ virtual sal_Bool SAL_CALL has(css::uno::Any const & aElement) override;
+
+ virtual void SAL_CALL insert(css::uno::Any const & aElement) override;
+
+ virtual void SAL_CALL remove(css::uno::Any const & aElement) override;
+
+ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL
+ createContentEnumeration(OUString const & aServiceName) override;
+
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ virtual void SAL_CALL setPropertyValue(
+ OUString const & aPropertyName, css::uno::Any const & aValue) override;
+
+ virtual css::uno::Any SAL_CALL getPropertyValue(
+ OUString const & PropertyName) override;
+
+ virtual void SAL_CALL addPropertyChangeListener(
+ OUString const & aPropertyName,
+ css::uno::Reference< css::beans::XPropertyChangeListener > const &
+ xListener) override;
+
+ virtual void SAL_CALL removePropertyChangeListener(
+ OUString const & aPropertyName,
+ css::uno::Reference< css::beans::XPropertyChangeListener > const &
+ aListener) override;
+
+ virtual void SAL_CALL addVetoableChangeListener(
+ OUString const & PropertyName,
+ css::uno::Reference< css::beans::XVetoableChangeListener > const &
+ aListener) override;
+
+ virtual void SAL_CALL removeVetoableChangeListener(
+ OUString const & PropertyName,
+ css::uno::Reference< css::beans::XVetoableChangeListener > const &
+ aListener) override;
+
+ virtual css::uno::Sequence< css::beans::Property > SAL_CALL getProperties() override;
+
+ virtual css::beans::Property SAL_CALL getPropertyByName(
+ OUString const & aName) override;
+
+ virtual sal_Bool SAL_CALL hasPropertyByName(OUString const & Name) override;
+
+ virtual void SAL_CALL disposing(css::lang::EventObject const & Source) override;
+
+ virtual void SAL_CALL initialize(
+ css::uno::Sequence<css::uno::Any> const & aArguments)
+ override;
+
+ // needs to be called with rBHelper.rMutex locked:
+ bool isDisposed() const { return rBHelper.bDisposed || rBHelper.bInDispose; }
+
+ void removeEventListenerFromComponent(
+ css::uno::Reference< css::lang::XComponent > const & component);
+
+ void readRdbDirectory(std::u16string_view uri, bool optional);
+
+ void readRdbFile(OUString const & uri, bool optional);
+
+ bool readLegacyRdbFile(OUString const & uri);
+
+ OUString readLegacyRdbString(
+ std::u16string_view uri, RegistryKey & key,
+ OUString const & path);
+
+ void readLegacyRdbStrings(
+ std::u16string_view uri, RegistryKey & key,
+ OUString const & path, std::vector< OUString > * strings);
+
+ void insertRdbFiles(
+ std::vector< OUString > const & uris,
+ css::uno::Reference< css::uno::XComponentContext > const &
+ alientContext);
+
+ void insertLegacyFactory(
+ css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo);
+
+ bool insertExtraData(Data const & extra);
+
+ void removeRdbFiles(std::vector< OUString > const & uris);
+
+ bool removeLegacyFactory(
+ css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo,
+ bool removeListener);
+
+ void removeImplementation(const OUString & name);
+
+ std::shared_ptr< Data::Implementation > findServiceImplementation(
+ css::uno::Reference< css::uno::XComponentContext > const & context,
+ OUString const & specifier);
+
+ void preloadImplementations();
+
+ css::uno::Reference< css::uno::XComponentContext > context_;
+ Data data_;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/shlib.cxx b/cppuhelper/source/shlib.cxx
new file mode 100644
index 000000000..b270c62c5
--- /dev/null
+++ b/cppuhelper/source/shlib.cxx
@@ -0,0 +1,437 @@
+/* -*- 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 <cassert>
+#include <cstdlib>
+#include <string_view>
+
+#ifdef IOS
+#include <premac.h>
+#include <Foundation/Foundation.h>
+#include <postmac.h>
+#endif
+
+#include <com/sun/star/loader/CannotActivateFactoryException.hpp>
+#include <com/sun/star/registry/CannotRegisterImplementationException.hpp>
+#include <com/sun/star/registry/XRegistryKey.hpp>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/shlib.hxx>
+#include <o3tl/string_view.hxx>
+#include <osl/module.hxx>
+#include <sal/log.hxx>
+#include <uno/environment.hxx>
+#include <uno/mapping.hxx>
+
+#include "loadsharedlibcomponentfactory.hxx"
+
+#if defined DISABLE_DYNLOADING
+#include <osl/detail/component-mapping.h>
+#endif
+
+css::uno::Environment cppuhelper::detail::getEnvironment(
+ OUString const & name, std::u16string_view implementation)
+{
+ OUString n(name);
+ if (!implementation.empty()) {
+ static char const * log = std::getenv("UNO_ENV_LOG");
+ if (log != nullptr && *log != 0) {
+ OString imps(log);
+ for (sal_Int32 i = 0; i != -1;) {
+ std::string_view imp(o3tl::getToken(imps, 0, ';', i));
+ //TODO: this assumes UNO_ENV_LOG only contains ASCII characters:
+ if (o3tl::equalsAscii(implementation, imp))
+ {
+ n += ":log";
+ break;
+ }
+ }
+ }
+ }
+ return css::uno::Environment(n);
+}
+
+namespace {
+
+#if !defined DISABLE_DYNLOADING
+
+css::uno::Environment getEnvironmentFromModule(
+ osl::Module const & module, css::uno::Environment const & target,
+ std::u16string_view implementation, OUString const & prefix)
+{
+ char const * name = nullptr;
+ css::uno::Environment env;
+ OUString fullPrefix(prefix);
+ if (!fullPrefix.isEmpty()) {
+ fullPrefix += "_";
+ }
+ component_getImplementationEnvironmentExtFunc fp1
+ = reinterpret_cast<component_getImplementationEnvironmentExtFunc>(
+ module.getFunctionSymbol(fullPrefix + COMPONENT_GETENVEXT));
+ if (fp1 != nullptr) {
+ (*fp1)(
+ &name, reinterpret_cast<uno_Environment **>(&env),
+ (OUStringToOString(implementation, RTL_TEXTENCODING_ASCII_US)
+ .getStr()),
+ target.get());
+ } else {
+ component_getImplementationEnvironmentFunc fp2
+ = reinterpret_cast<component_getImplementationEnvironmentFunc>(
+ module.getFunctionSymbol(fullPrefix + COMPONENT_GETENV));
+ if (fp2 != nullptr) {
+ (*fp2)(&name, reinterpret_cast<uno_Environment **>(&env));
+ } else {
+ name = CPPU_CURRENT_LANGUAGE_BINDING_NAME; //TODO: fail
+ }
+ }
+ if (!env.is() && name != nullptr) {
+ env = cppuhelper::detail::getEnvironment(
+ OUString::createFromAscii(name), implementation);
+ }
+ return env;
+}
+
+#endif
+
+extern "C" void getFactory(va_list * args) {
+ component_getFactoryFunc fn = va_arg(*args, component_getFactoryFunc);
+ OString const * implementation = va_arg(*args, OString const *);
+ void * smgr = va_arg(*args, void *);
+ void ** factory = va_arg(*args, void **);
+ *factory = (*fn)(implementation->getStr(), smgr, nullptr);
+}
+
+css::uno::Reference<css::uno::XInterface> invokeComponentFactory(
+ css::uno::Environment const & source, css::uno::Environment const & target,
+ component_getFactoryFunc function, std::u16string_view uri,
+ std::u16string_view implementation,
+ css::uno::Reference<css::lang::XMultiServiceFactory> const & serviceManager)
+{
+ if (!(source.is() && target.is())) {
+ throw css::loader::CannotActivateFactoryException(
+ "cannot get environments",
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ OString impl(
+ OUStringToOString(implementation, RTL_TEXTENCODING_ASCII_US));
+ if (source.get() == target.get()) {
+ return css::uno::Reference<css::uno::XInterface>(
+ static_cast<css::uno::XInterface *>(
+ (*function)(impl.getStr(), serviceManager.get(), nullptr)),
+ SAL_NO_ACQUIRE);
+ }
+ css::uno::Mapping mapTo(source, target);
+ css::uno::Mapping mapFrom(target, source);
+ if (!(mapTo.is() && mapFrom.is())) {
+ throw css::loader::CannotActivateFactoryException(
+ "cannot get mappings",
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ void * smgr = mapTo.mapInterface(
+ serviceManager.get(),
+ cppu::UnoType<css::lang::XMultiServiceFactory>::get());
+ void * factory = nullptr;
+ target.invoke(getFactory, function, &impl, smgr, &factory);
+ if (smgr != nullptr) {
+ (*target.get()->pExtEnv->releaseInterface)(
+ target.get()->pExtEnv, smgr);
+ }
+ if (factory == nullptr) {
+ throw css::loader::CannotActivateFactoryException(
+ (OUString::Concat("calling factory function for \"") + implementation + "\" in <"
+ + uri + "> returned null"),
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ css::uno::Reference<css::uno::XInterface> res;
+ mapFrom.mapInterface(
+ reinterpret_cast<void **>(&res), factory,
+ cppu::UnoType<css::uno::XInterface>::get());
+ (*target.get()->pExtEnv->releaseInterface)(
+ target.get()->pExtEnv, factory);
+ return res;
+}
+
+#if !defined DISABLE_DYNLOADING
+
+extern "C" void getInstance(va_list * args) {
+ cppuhelper::ImplementationConstructorFn * fn = va_arg(*args, cppuhelper::ImplementationConstructorFn *);
+ void * ctxt = va_arg(*args, void *);
+ assert(ctxt);
+ void * argseq = va_arg(*args, void *);
+ assert(argseq);
+ void ** instance = va_arg(*args, void **);
+ assert(instance);
+ assert(*instance == nullptr);
+ *instance = (*fn)(static_cast<css::uno::XComponentContext*>(ctxt),
+ *static_cast<css::uno::Sequence<css::uno::Any> const*>(argseq));
+}
+
+cppuhelper::WrapperConstructorFn mapConstructorFn(
+ css::uno::Environment const & source, css::uno::Environment const & target,
+ cppuhelper::ImplementationConstructorFn *const constructorFunction)
+{
+ if (!(source.is() && target.is())) {
+ throw css::loader::CannotActivateFactoryException(
+ "cannot get environments",
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ if (source.get() == target.get()) {
+ return cppuhelper::WrapperConstructorFn(constructorFunction);
+ }
+ // note: it should be valid to capture these mappings because they are
+ // ref-counted, and the returned closure will always be invoked in the
+ // "source" environment
+ css::uno::Mapping mapTo(source, target);
+ css::uno::Mapping mapFrom(target, source);
+ if (!(mapTo.is() && mapFrom.is())) {
+ throw css::loader::CannotActivateFactoryException(
+ "cannot get mappings",
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ return [mapFrom, mapTo, target, constructorFunction]
+ (css::uno::XComponentContext *const context, css::uno::Sequence<css::uno::Any> const& args)
+ {
+ void *const ctxt = mapTo.mapInterface(
+ context,
+ cppu::UnoType<css::uno::XComponentContext>::get());
+ if (args.hasElements()) {
+ std::abort(); // TODO map args
+ }
+ void * instance = nullptr;
+ target.invoke(getInstance, constructorFunction, ctxt, &args, &instance);
+ if (ctxt != nullptr) {
+ (*target.get()->pExtEnv->releaseInterface)(
+ target.get()->pExtEnv, ctxt);
+ }
+ css::uno::XInterface * res = nullptr;
+ if (instance == nullptr) {
+ return res;
+ }
+ mapFrom.mapInterface(
+ reinterpret_cast<void **>(&res), instance,
+ cppu::UnoType<css::uno::XInterface>::get());
+ (*target.get()->pExtEnv->releaseInterface)(
+ target.get()->pExtEnv, instance);
+ return res;
+ };
+}
+
+#endif
+
+}
+
+void cppuhelper::detail::loadSharedLibComponentFactory(
+ OUString const & uri, OUString const & environment,
+ OUString const & prefix, OUString const & implementation,
+ OUString const & constructor,
+ css::uno::Reference<css::lang::XMultiServiceFactory> const & serviceManager,
+ WrapperConstructorFn * constructorFunction,
+ css::uno::Reference<css::uno::XInterface> * factory)
+{
+ assert(constructor.isEmpty() || !environment.isEmpty());
+ assert(
+ (constructorFunction == nullptr && constructor.isEmpty())
+ || !*constructorFunction);
+ assert(factory != nullptr && !factory->is());
+#if defined DISABLE_DYNLOADING
+ assert(!environment.isEmpty());
+ if (constructor.isEmpty()) {
+ css::uno::Environment curEnv(css::uno::Environment::getCurrent());
+ css::uno::Environment env(getEnvironment(environment, implementation));
+ if (!(curEnv.is() && env.is())) {
+ throw css::loader::CannotActivateFactoryException(
+ "cannot get environments",
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ if (curEnv.get() != env.get()) {
+ std::abort();//TODO
+ }
+ SAL_INFO("cppuhelper.shlib", "prefix=" << prefix << " implementation=" << implementation << " uri=" << uri);
+ lib_to_factory_mapping const * map = lo_get_factory_map();
+ component_getFactoryFunc fp = 0;
+ for (int i = 0; map[i].name != 0; ++i) {
+ if (uri.equalsAscii(map[i].name)) {
+ fp = map[i].component_getFactory_function;
+ break;
+ }
+ }
+ if (fp == 0) {
+ SAL_WARN("cppuhelper", "unknown factory name \"" << uri << "\"");
+#ifdef IOS
+ NSLog(@"Unknown factory %s", uri.toUtf8().getStr());
+#endif
+ throw css::loader::CannotActivateFactoryException(
+ "unknown factory name \"" + uri + "\"",
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ *factory = invokeComponentFactory(
+ css::uno::Environment::getCurrent(),
+ getEnvironment(environment, implementation), fp, uri,
+ implementation, serviceManager);
+ } else {
+ SAL_INFO("cppuhelper.shlib", "constructor=" << constructor);
+ lib_to_constructor_mapping const * map = lo_get_constructor_map();
+ for (int i = 0; map[i].name != 0; ++i) {
+ if (constructor.equalsAscii(map[i].name)) {
+ *constructorFunction
+ = reinterpret_cast<ImplementationConstructorFn *>(
+ map[i].constructor_function);
+ return;
+ }
+ }
+ SAL_WARN("cppuhelper", "unknown constructor name \"" << constructor << "\"");
+#ifdef IOS
+ NSLog(@"Unknown constructor %s", constructor.toUtf8().getStr());
+#endif
+ throw css::loader::CannotActivateFactoryException(
+ "unknown constructor name \"" + constructor + "\"",
+ css::uno::Reference<css::uno::XInterface>());
+ }
+#else
+ osl::Module mod(uri, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL);
+ if (!mod.is()) {
+ throw css::loader::CannotActivateFactoryException(
+ "loading component library <" + uri + "> failed",
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ if (constructor.isEmpty()) {
+ OUString sym;
+ SAL_INFO("cppuhelper.shlib", "prefix=" << prefix << " implementation=" << implementation << " uri=" << uri);
+ if (!prefix.isEmpty()) {
+ sym = prefix + "_" COMPONENT_GETFACTORY;
+ } else {
+ sym = COMPONENT_GETFACTORY;
+ }
+ oslGenericFunction fp = mod.getFunctionSymbol(sym);
+ if (fp == nullptr) {
+ throw css::loader::CannotActivateFactoryException(
+ ("no factory symbol \"" + sym + "\" in component library <"
+ + uri + ">"),
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ css::uno::Environment curEnv(css::uno::Environment::getCurrent());
+ *factory = invokeComponentFactory(
+ curEnv,
+ (environment.isEmpty()
+ ? getEnvironmentFromModule(mod, curEnv, implementation, prefix)
+ : getEnvironment(environment, implementation)),
+ reinterpret_cast<component_getFactoryFunc>(fp), uri, implementation,
+ serviceManager);
+ } else {
+ SAL_INFO("cppuhelper.shlib", "constructor=" << constructor);
+ oslGenericFunction fp = mod.getFunctionSymbol(constructor);
+ if (fp == nullptr) {
+ throw css::loader::CannotActivateFactoryException(
+ ("no constructor symbol \"" + constructor
+ + "\" in component library <" + uri + ">"),
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ css::uno::Environment curEnv(css::uno::Environment::getCurrent());
+ *constructorFunction = mapConstructorFn(
+ curEnv,
+ (environment.isEmpty()
+ ? getEnvironmentFromModule(mod, curEnv, implementation, prefix)
+ : getEnvironment(environment, implementation)),
+ reinterpret_cast<ImplementationConstructorFn *>(fp));
+ }
+ mod.release();
+#endif
+}
+
+css::uno::Reference<css::uno::XInterface> cppu::loadSharedLibComponentFactory(
+ OUString const & uri, OUString const & rPath,
+ OUString const & rImplName,
+ css::uno::Reference<css::lang::XMultiServiceFactory> const & xMgr,
+ css::uno::Reference<css::registry::XRegistryKey> const & xKey)
+{
+ assert(rPath.isEmpty()); (void) rPath;
+ assert(!xKey.is()); (void) xKey;
+ css::uno::Reference<css::uno::XInterface> fac;
+ cppuhelper::detail::loadSharedLibComponentFactory(
+ uri, "", "", rImplName, "", xMgr, nullptr, &fac);
+ return fac;
+}
+
+#if !defined DISABLE_DYNLOADING
+
+namespace {
+
+extern "C" void writeInfo(va_list * args) {
+ component_writeInfoFunc fn = va_arg(*args, component_writeInfoFunc);
+ void * smgr = va_arg(*args, void *);
+ void * key = va_arg(*args, void *);
+ sal_Bool * ok = va_arg(*args, sal_Bool *);
+ *ok = (*fn)(smgr, key);
+}
+
+}
+
+void cppu::writeSharedLibComponentInfo(
+ OUString const & uri, OUString const & rPath,
+ css::uno::Reference<css::lang::XMultiServiceFactory> const & xMgr,
+ css::uno::Reference<css::registry::XRegistryKey> const & xKey)
+{
+ assert(rPath.isEmpty()); (void) rPath;
+ osl::Module mod(uri, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL);
+ if (!mod.is()) {
+ throw css::registry::CannotRegisterImplementationException(
+ "loading component library <" + uri + "> failed",
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ oslGenericFunction fp = mod.getFunctionSymbol(COMPONENT_WRITEINFO);
+ if (fp == nullptr) {
+ throw css::registry::CannotRegisterImplementationException(
+ ("no symbol \"" COMPONENT_WRITEINFO "\" in component library <"
+ + uri + ">"),
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ css::uno::Environment curEnv(css::uno::Environment::getCurrent());
+ css::uno::Environment env(getEnvironmentFromModule(mod, curEnv, u"", ""));
+ if (!(curEnv.is() && env.is())) {
+ throw css::registry::CannotRegisterImplementationException(
+ "cannot get environments",
+ css::uno::Reference<css::uno::XInterface>());
+ }
+ css::uno::Mapping map(curEnv, env);
+ if (!map.is()) {
+ throw css::registry::CannotRegisterImplementationException(
+ "cannot get mapping", css::uno::Reference<css::uno::XInterface>());
+ }
+ void * smgr = map.mapInterface(
+ xMgr.get(), cppu::UnoType<css::lang::XMultiServiceFactory>::get());
+ void * key = map.mapInterface(
+ xKey.get(), cppu::UnoType<css::registry::XRegistryKey>::get());
+ sal_Bool ok;
+ env.invoke(writeInfo, fp, smgr, key, &ok);
+ (*env.get()->pExtEnv->releaseInterface)(env.get()->pExtEnv, key);
+ if (smgr != nullptr) {
+ (*env.get()->pExtEnv->releaseInterface)(env.get()->pExtEnv, smgr);
+ }
+ if (!ok) {
+ throw css::registry::CannotRegisterImplementationException(
+ ("calling \"" COMPONENT_WRITEINFO "\" in component library <" + uri
+ + "> returned false"),
+ css::uno::Reference<css::uno::XInterface>());
+ }
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/supportsservice.cxx b/cppuhelper/source/supportsservice.cxx
new file mode 100644
index 000000000..40dca8c0c
--- /dev/null
+++ b/cppuhelper/source/supportsservice.cxx
@@ -0,0 +1,27 @@
+/* -*- 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 <algorithm>
+#include <cassert>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <rtl/ustring.hxx>
+
+bool cppu::supportsService(css::lang::XServiceInfo* implementation, OUString const& name)
+{
+ assert(implementation != nullptr);
+ const css::uno::Sequence<OUString> s(implementation->getSupportedServiceNames());
+ return std::find(s.begin(), s.end(), name) != s.end();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/tdmgr.cxx b/cppuhelper/source/tdmgr.cxx
new file mode 100644
index 000000000..1e5826e24
--- /dev/null
+++ b/cppuhelper/source/tdmgr.cxx
@@ -0,0 +1,660 @@
+/* -*- 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 <sal/log.hxx>
+
+#include <vector>
+
+#include <osl/diagnose.h>
+#include <rtl/ustring.hxx>
+
+#include <uno/lbnames.h>
+#include <uno/mapping.hxx>
+
+#include <cppuhelper/bootstrap.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <typelib/typedescription.h>
+
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/reflection/XTypeDescription.hpp>
+#include <com/sun/star/reflection/XEnumTypeDescription.hpp>
+#include <com/sun/star/reflection/XIndirectTypeDescription.hpp>
+#include <com/sun/star/reflection/XInterfaceMemberTypeDescription.hpp>
+#include <com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp>
+#include <com/sun/star/reflection/XMethodParameter.hpp>
+#include <com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp>
+#include <com/sun/star/reflection/XInterfaceTypeDescription2.hpp>
+#include <com/sun/star/reflection/XCompoundTypeDescription.hpp>
+#include <com/sun/star/reflection/XStructTypeDescription.hpp>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::reflection;
+
+namespace cppu
+{
+
+static typelib_TypeDescription * createCTD(
+ Reference< container::XHierarchicalNameAccess > const & access,
+ const Reference< XTypeDescription > & xType );
+
+
+static typelib_TypeDescription * createCTD(
+ const Reference< XCompoundTypeDescription > & xType )
+{
+ typelib_TypeDescription * pRet = nullptr;
+ if (xType.is())
+ {
+ typelib_TypeDescription * pBaseType = createCTD(
+ Reference< XCompoundTypeDescription >::query( xType->getBaseType() ) );
+ if (pBaseType)
+ typelib_typedescription_register( &pBaseType );
+
+ // construct member init array
+ const Sequence<Reference< XTypeDescription > > & rMemberTypes = xType->getMemberTypes();
+ const Sequence< OUString > & rMemberNames = xType->getMemberNames();
+
+ const Reference< XTypeDescription > * pMemberTypes = rMemberTypes.getConstArray();
+ const OUString * pMemberNames = rMemberNames.getConstArray();
+
+ sal_Int32 nMembers = rMemberTypes.getLength();
+ OSL_ENSURE( nMembers == rMemberNames.getLength(), "### lens differ!" );
+
+ OUString aTypeName( xType->getName() );
+
+ typelib_CompoundMember_Init * pMemberInits = static_cast<typelib_CompoundMember_Init *>(alloca(
+ sizeof(typelib_CompoundMember_Init) * nMembers ));
+
+ sal_Int32 nPos;
+ for ( nPos = nMembers; nPos--; )
+ {
+ typelib_CompoundMember_Init & rInit = pMemberInits[nPos];
+ rInit.eTypeClass = static_cast<typelib_TypeClass>(pMemberTypes[nPos]->getTypeClass());
+
+ OUString aMemberTypeName( pMemberTypes[nPos]->getName() );
+ rInit.pTypeName = aMemberTypeName.pData;
+ rtl_uString_acquire( rInit.pTypeName );
+
+ // string is held by rMemberNames
+ rInit.pMemberName = pMemberNames[nPos].pData;
+ }
+
+ typelib_typedescription_new(
+ &pRet,
+ static_cast<typelib_TypeClass>(xType->getTypeClass()),
+ aTypeName.pData,
+ (pBaseType ? pBaseType->pWeakRef : nullptr),
+ nMembers, pMemberInits );
+
+ // cleanup
+ for ( nPos = nMembers; nPos--; )
+ {
+ rtl_uString_release( pMemberInits[nPos].pTypeName );
+ }
+ if (pBaseType)
+ typelib_typedescription_release( pBaseType );
+ }
+ return pRet;
+}
+
+static typelib_TypeDescription * createCTD(
+ Reference< container::XHierarchicalNameAccess > const & access,
+ const Reference< XStructTypeDescription > & xType )
+{
+ typelib_TypeDescription * pRet = nullptr;
+ if (xType.is() && !xType->getTypeParameters().hasElements())
+ {
+ typelib_TypeDescription * pBaseType = createCTD(
+ access, xType->getBaseType() );
+ if (pBaseType)
+ typelib_typedescription_register( &pBaseType );
+
+ // construct member init array
+ const Sequence<Reference< XTypeDescription > > & rMemberTypes = xType->getMemberTypes();
+ const Sequence< OUString > & rMemberNames = xType->getMemberNames();
+
+ const Reference< XTypeDescription > * pMemberTypes = rMemberTypes.getConstArray();
+ const OUString * pMemberNames = rMemberNames.getConstArray();
+
+ sal_Int32 nMembers = rMemberTypes.getLength();
+ OSL_ENSURE( nMembers == rMemberNames.getLength(), "### lens differ!" );
+
+ OUString aTypeName( xType->getName() );
+
+ typelib_StructMember_Init * pMemberInits = static_cast<typelib_StructMember_Init *>(alloca(
+ sizeof(typelib_StructMember_Init) * nMembers ));
+
+ Sequence< Reference< XTypeDescription > > templateMemberTypes;
+ sal_Int32 i = aTypeName.indexOf('<');
+ if (i >= 0) {
+ Reference< XStructTypeDescription > templateDesc(
+ access->getByHierarchicalName(aTypeName.copy(0, i)),
+ UNO_QUERY_THROW);
+ OSL_ASSERT(
+ templateDesc->getTypeParameters().getLength()
+ == xType->getTypeArguments().getLength());
+ templateMemberTypes = templateDesc->getMemberTypes();
+ OSL_ASSERT(templateMemberTypes.getLength() == nMembers);
+ }
+
+ sal_Int32 nPos;
+ for ( nPos = nMembers; nPos--; )
+ {
+ typelib_StructMember_Init & rInit = pMemberInits[nPos];
+ rInit.aBase.eTypeClass
+ = static_cast<typelib_TypeClass>(pMemberTypes[nPos]->getTypeClass());
+
+ OUString aMemberTypeName( pMemberTypes[nPos]->getName() );
+ rInit.aBase.pTypeName = aMemberTypeName.pData;
+ rtl_uString_acquire( rInit.aBase.pTypeName );
+
+ // string is held by rMemberNames
+ rInit.aBase.pMemberName = pMemberNames[nPos].pData;
+
+ rInit.bParameterizedType = templateMemberTypes.hasElements()
+ && (templateMemberTypes[nPos]->getTypeClass()
+ == TypeClass_UNKNOWN);
+ }
+
+ typelib_typedescription_newStruct(
+ &pRet,
+ aTypeName.pData,
+ (pBaseType ? pBaseType->pWeakRef : nullptr),
+ nMembers, pMemberInits );
+
+ // cleanup
+ for ( nPos = nMembers; nPos--; )
+ {
+ rtl_uString_release( pMemberInits[nPos].aBase.pTypeName );
+ }
+ if (pBaseType)
+ typelib_typedescription_release( pBaseType );
+ }
+ return pRet;
+}
+
+static typelib_TypeDescription * createCTD(
+ const Reference< XInterfaceAttributeTypeDescription2 > & xAttribute )
+{
+ typelib_TypeDescription * pRet = nullptr;
+ if (xAttribute.is())
+ {
+ OUString aMemberName( xAttribute->getName() );
+ Reference< XTypeDescription > xType( xAttribute->getType() );
+ OUString aMemberTypeName( xType->getName() );
+ std::vector< rtl_uString * > getExc;
+ const Sequence< Reference< XCompoundTypeDescription > > getExcs(
+ xAttribute->getGetExceptions() );
+ for (const auto & ctd : getExcs)
+ {
+ OSL_ASSERT( ctd.is() );
+ getExc.push_back( ctd->getName().pData );
+ }
+ std::vector< rtl_uString * > setExc;
+ const Sequence< Reference< XCompoundTypeDescription > > setExcs(
+ xAttribute->getSetExceptions() );
+ for (const auto & ctd : setExcs)
+ {
+ OSL_ASSERT( ctd.is() );
+ setExc.push_back( ctd->getName().pData );
+ }
+ typelib_typedescription_newExtendedInterfaceAttribute(
+ reinterpret_cast<typelib_InterfaceAttributeTypeDescription **>(&pRet),
+ xAttribute->getPosition(),
+ aMemberName.pData, // name
+ static_cast<typelib_TypeClass>(xType->getTypeClass()),
+ aMemberTypeName.pData, // type name
+ xAttribute->isReadOnly(),
+ getExc.size(), getExc.data(),
+ setExc.size(), setExc.data() );
+ }
+ return pRet;
+}
+
+static typelib_TypeDescription * createCTD(
+ const Reference< XInterfaceMethodTypeDescription > & xMethod )
+{
+ typelib_TypeDescription * pRet = nullptr;
+ if (xMethod.is())
+ {
+ Reference< XTypeDescription > xReturnType( xMethod->getReturnType() );
+
+ // init all params
+ const Sequence<Reference< XMethodParameter > > & rParams = xMethod->getParameters();
+ const Reference< XMethodParameter > * pParams = rParams.getConstArray();
+ sal_Int32 nParams = rParams.getLength();
+
+ typelib_Parameter_Init * pParamInit = static_cast<typelib_Parameter_Init *>(alloca(
+ sizeof(typelib_Parameter_Init) * nParams ));
+
+ sal_Int32 nPos;
+ for ( nPos = nParams; nPos--; )
+ {
+ const Reference< XMethodParameter > & xParam = pParams[nPos];
+ const Reference< XTypeDescription > & xType = xParam->getType();
+ typelib_Parameter_Init & rInit = pParamInit[xParam->getPosition()];
+
+ rInit.eTypeClass = static_cast<typelib_TypeClass>(xType->getTypeClass());
+ OUString aParamTypeName( xType->getName() );
+ rInit.pTypeName = aParamTypeName.pData;
+ rtl_uString_acquire( rInit.pTypeName );
+ OUString aParamName( xParam->getName() );
+ rInit.pParamName = aParamName.pData;
+ rtl_uString_acquire( rInit.pParamName );
+ rInit.bIn = xParam->isIn();
+ rInit.bOut = xParam->isOut();
+ }
+
+ // init all exception strings
+ const Sequence<Reference< XTypeDescription > > & rExceptions = xMethod->getExceptions();
+ const Reference< XTypeDescription > * pExceptions = rExceptions.getConstArray();
+ sal_Int32 nExceptions = rExceptions.getLength();
+ rtl_uString ** ppExceptionNames = static_cast<rtl_uString **>(alloca(
+ sizeof(rtl_uString *) * nExceptions ));
+
+ for ( nPos = nExceptions; nPos--; )
+ {
+ OUString aExceptionTypeName( pExceptions[nPos]->getName() );
+ ppExceptionNames[nPos] = aExceptionTypeName.pData;
+ rtl_uString_acquire( ppExceptionNames[nPos] );
+ }
+
+ OUString aTypeName( xMethod->getName() );
+ OUString aReturnTypeName( xReturnType->getName() );
+
+ typelib_typedescription_newInterfaceMethod(
+ reinterpret_cast<typelib_InterfaceMethodTypeDescription **>(&pRet),
+ xMethod->getPosition(),
+ xMethod->isOneway(),
+ aTypeName.pData,
+ static_cast<typelib_TypeClass>(xReturnType->getTypeClass()),
+ aReturnTypeName.pData,
+ nParams, pParamInit,
+ nExceptions, ppExceptionNames );
+
+ for ( nPos = nParams; nPos--; )
+ {
+ rtl_uString_release( pParamInit[nPos].pTypeName );
+ rtl_uString_release( pParamInit[nPos].pParamName );
+ }
+ for ( nPos = nExceptions; nPos--; )
+ {
+ rtl_uString_release( ppExceptionNames[nPos] );
+ }
+ }
+ return pRet;
+}
+
+static typelib_TypeDescription * createCTD(
+ Reference< container::XHierarchicalNameAccess > const & access,
+ const Reference< XInterfaceTypeDescription2 > & xType )
+{
+ typelib_TypeDescription * pRet = nullptr;
+ if (xType.is())
+ {
+ Sequence< Reference< XTypeDescription > > aBases(xType->getBaseTypes());
+ sal_Int32 nBases = aBases.getLength();
+ // Exploit the fact that a typelib_TypeDescription for an interface type
+ // is also the typelib_TypeDescriptionReference for that type:
+ std::unique_ptr< typelib_TypeDescription * []> aBaseTypes(
+ new typelib_TypeDescription *[nBases]);
+ for (sal_Int32 i = 0; i < nBases; ++i) {
+ typelib_TypeDescription * p = createCTD(access, aBases[i]);
+ OSL_ASSERT(
+ !TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK(p->eTypeClass));
+ typelib_typedescription_register(&p);
+ aBaseTypes[i] = p;
+ }
+ typelib_TypeDescriptionReference ** pBaseTypeRefs
+ = reinterpret_cast< typelib_TypeDescriptionReference ** >(
+ aBaseTypes.get());
+
+ // construct all member refs
+ const Sequence<Reference< XInterfaceMemberTypeDescription > > & rMembers = xType->getMembers();
+ sal_Int32 nMembers = rMembers.getLength();
+
+ typelib_TypeDescriptionReference ** ppMemberRefs = static_cast<typelib_TypeDescriptionReference **>(alloca(
+ sizeof(typelib_TypeDescriptionReference *) * nMembers ));
+
+ const Reference< XInterfaceMemberTypeDescription > * pMembers = rMembers.getConstArray();
+
+ OUString aTypeName( xType->getName() );
+
+ sal_Int32 nPos;
+ for ( nPos = nMembers; nPos--; )
+ {
+ OUString aMemberTypeName( pMembers[nPos]->getName() );
+ ppMemberRefs[nPos] = nullptr;
+ typelib_typedescriptionreference_new(
+ ppMemberRefs + nPos,
+ static_cast<typelib_TypeClass>(pMembers[nPos]->getTypeClass()),
+ aMemberTypeName.pData );
+ }
+
+ typelib_typedescription_newMIInterface(
+ reinterpret_cast<typelib_InterfaceTypeDescription **>(&pRet),
+ aTypeName.pData,
+ 0, 0, 0, 0, 0,
+ nBases, pBaseTypeRefs,
+ nMembers, ppMemberRefs );
+
+ // cleanup refs and base type
+ for (int i = 0; i < nBases; ++i) {
+ typelib_typedescription_release(aBaseTypes[i]);
+ }
+
+ for ( nPos = nMembers; nPos--; )
+ {
+ typelib_typedescriptionreference_release( ppMemberRefs[nPos] );
+ }
+ }
+ return pRet;
+}
+
+static typelib_TypeDescription * createCTD( const Reference< XEnumTypeDescription > & xType )
+{
+ typelib_TypeDescription * pRet = nullptr;
+ if (xType.is())
+ {
+ OUString aTypeName( xType->getName() );
+ Sequence< OUString > aNames( xType->getEnumNames() );
+ OSL_ASSERT( sizeof(OUString) == sizeof(rtl_uString *) ); // !!!
+ Sequence< sal_Int32 > aValues( xType->getEnumValues() );
+
+ typelib_typedescription_newEnum(
+ &pRet, aTypeName.pData, xType->getDefaultEnumValue(),
+ aNames.getLength(),
+ const_cast<rtl_uString **>(reinterpret_cast<rtl_uString * const *>(aNames.getConstArray())),
+ const_cast< sal_Int32 * >( aValues.getConstArray() ) );
+ }
+ return pRet;
+}
+
+static typelib_TypeDescription * createCTD(
+ Reference< container::XHierarchicalNameAccess > const & access,
+ const Reference< XIndirectTypeDescription > & xType )
+{
+ typelib_TypeDescription * pRet = nullptr;
+ if (xType.is())
+ {
+ typelib_TypeDescription * pRefType = createCTD(
+ access, xType->getReferencedType() );
+ typelib_typedescription_register( &pRefType );
+
+ OUString aTypeName( xType->getName() );
+
+ typelib_typedescription_new(
+ &pRet,
+ static_cast<typelib_TypeClass>(xType->getTypeClass()),
+ aTypeName.pData,
+ pRefType->pWeakRef,
+ 0, nullptr );
+
+ // cleanup
+ typelib_typedescription_release( pRefType );
+ }
+ return pRet;
+}
+
+
+static typelib_TypeDescription * createCTD(
+ Reference< container::XHierarchicalNameAccess > const & access,
+ const Reference< XTypeDescription > & xType )
+{
+ typelib_TypeDescription * pRet = nullptr;
+
+ if (xType.is())
+ {
+ switch (xType->getTypeClass())
+ {
+ // built in types
+ case TypeClass_VOID:
+ {
+ OUString aTypeName("void");
+ typelib_typedescription_new( &pRet, typelib_TypeClass_VOID, aTypeName.pData, nullptr, 0, nullptr );
+ break;
+ }
+ case TypeClass_CHAR:
+ {
+ OUString aTypeName("char");
+ typelib_typedescription_new( &pRet, typelib_TypeClass_CHAR, aTypeName.pData, nullptr, 0, nullptr );
+ break;
+ }
+ case TypeClass_BOOLEAN:
+ {
+ OUString aTypeName("boolean");
+ typelib_typedescription_new( &pRet, typelib_TypeClass_BOOLEAN, aTypeName.pData, nullptr, 0, nullptr );
+ break;
+ }
+ case TypeClass_BYTE:
+ {
+ OUString aTypeName("byte");
+ typelib_typedescription_new( &pRet, typelib_TypeClass_BYTE, aTypeName.pData, nullptr, 0, nullptr );
+ break;
+ }
+ case TypeClass_SHORT:
+ {
+ OUString aTypeName("short");
+ typelib_typedescription_new( &pRet, typelib_TypeClass_SHORT, aTypeName.pData, nullptr, 0, nullptr );
+ break;
+ }
+ case TypeClass_UNSIGNED_SHORT:
+ {
+ OUString aTypeName("unsigned short");
+ typelib_typedescription_new( &pRet, typelib_TypeClass_UNSIGNED_SHORT, aTypeName.pData, nullptr, 0, nullptr );
+ break;
+ }
+ case TypeClass_LONG:
+ {
+ OUString aTypeName("long");
+ typelib_typedescription_new( &pRet, typelib_TypeClass_LONG, aTypeName.pData, nullptr, 0, nullptr );
+ break;
+ }
+ case TypeClass_UNSIGNED_LONG:
+ {
+ OUString aTypeName("unsigned long");
+ typelib_typedescription_new( &pRet, typelib_TypeClass_UNSIGNED_LONG, aTypeName.pData, nullptr, 0, nullptr );
+ break;
+ }
+ case TypeClass_HYPER:
+ {
+ OUString aTypeName("hyper");
+ typelib_typedescription_new( &pRet, typelib_TypeClass_HYPER, aTypeName.pData, nullptr, 0, nullptr );
+ break;
+ }
+ case TypeClass_UNSIGNED_HYPER:
+ {
+ OUString aTypeName("unsigned hyper");
+ typelib_typedescription_new( &pRet, typelib_TypeClass_UNSIGNED_HYPER, aTypeName.pData, nullptr, 0, nullptr );
+ break;
+ }
+ case TypeClass_FLOAT:
+ {
+ OUString aTypeName("float");
+ typelib_typedescription_new( &pRet, typelib_TypeClass_FLOAT, aTypeName.pData, nullptr, 0, nullptr );
+ break;
+ }
+ case TypeClass_DOUBLE:
+ {
+ OUString aTypeName("double");
+ typelib_typedescription_new( &pRet, typelib_TypeClass_DOUBLE, aTypeName.pData, nullptr, 0, nullptr );
+ break;
+ }
+ case TypeClass_STRING:
+ {
+ OUString aTypeName("string");
+ typelib_typedescription_new( &pRet, typelib_TypeClass_STRING, aTypeName.pData, nullptr, 0, nullptr );
+ break;
+ }
+ case TypeClass_TYPE:
+ {
+ OUString aTypeName("type");
+ typelib_typedescription_new( &pRet, typelib_TypeClass_TYPE, aTypeName.pData, nullptr, 0, nullptr );
+ break;
+ }
+ case TypeClass_ANY:
+ {
+ OUString aTypeName("any");
+ typelib_typedescription_new( &pRet, typelib_TypeClass_ANY, aTypeName.pData, nullptr, 0, nullptr );
+ break;
+ }
+
+ case TypeClass_EXCEPTION:
+ pRet = createCTD( Reference< XCompoundTypeDescription >::query( xType ) );
+ break;
+ case TypeClass_STRUCT:
+ pRet = createCTD(
+ access, Reference< XStructTypeDescription >::query( xType ) );
+ break;
+ case TypeClass_ENUM:
+ pRet = createCTD( Reference< XEnumTypeDescription >::query( xType ) );
+ break;
+ case TypeClass_TYPEDEF:
+ {
+ Reference< XIndirectTypeDescription > xTypedef( xType, UNO_QUERY );
+ if (xTypedef.is())
+ pRet = createCTD( access, xTypedef->getReferencedType() );
+ break;
+ }
+ case TypeClass_SEQUENCE:
+ pRet = createCTD(
+ access, Reference< XIndirectTypeDescription >::query( xType ) );
+ break;
+ case TypeClass_INTERFACE:
+ pRet = createCTD(
+ access,
+ Reference< XInterfaceTypeDescription2 >::query( xType ) );
+ break;
+ case TypeClass_INTERFACE_METHOD:
+ pRet = createCTD( Reference< XInterfaceMethodTypeDescription >::query( xType ) );
+ break;
+ case TypeClass_INTERFACE_ATTRIBUTE:
+ pRet = createCTD( Reference< XInterfaceAttributeTypeDescription2 >::query( xType ) );
+ break;
+ default:
+ break;
+ }
+ }
+
+ return pRet;
+}
+
+
+extern "C"
+{
+static void typelib_callback(
+ void * pContext, typelib_TypeDescription ** ppRet, rtl_uString * pTypeName )
+{
+ OSL_ENSURE( pContext && ppRet && pTypeName, "### null ptr!" );
+ if (!ppRet)
+ return;
+
+ if (*ppRet)
+ {
+ ::typelib_typedescription_release( *ppRet );
+ *ppRet = nullptr;
+ }
+ if (!(pContext && pTypeName))
+ return;
+
+ Reference< container::XHierarchicalNameAccess > access(
+ static_cast< container::XHierarchicalNameAccess * >(
+ pContext));
+ try
+ {
+ OUString const & rTypeName = OUString::unacquired( &pTypeName );
+ Reference< XTypeDescription > xTD;
+ if (access->getByHierarchicalName(rTypeName ) >>= xTD)
+ {
+ *ppRet = createCTD( access, xTD );
+ }
+ }
+ catch (const container::NoSuchElementException & exc)
+ {
+ SAL_INFO("cppuhelper", "typelibrary type not available: " << exc );
+ }
+ catch (const Exception & exc)
+ {
+ SAL_INFO("cppuhelper", exc );
+ }
+}
+}
+
+namespace {
+
+class EventListenerImpl
+ : public WeakImplHelper< lang::XEventListener >
+{
+ Reference< container::XHierarchicalNameAccess > m_xTDMgr;
+
+public:
+ explicit EventListenerImpl(
+ Reference< container::XHierarchicalNameAccess > const & xTDMgr )
+ : m_xTDMgr( xTDMgr )
+ {}
+
+ // XEventListener
+ virtual void SAL_CALL disposing( lang::EventObject const & rEvt ) override;
+};
+
+}
+
+void EventListenerImpl::disposing( lang::EventObject const & rEvt )
+{
+ if (rEvt.Source != m_xTDMgr) {
+ OSL_ASSERT(false);
+ }
+ // deregister of c typelib callback
+ ::typelib_typedescription_revokeCallback( m_xTDMgr.get(), typelib_callback );
+}
+
+
+sal_Bool SAL_CALL installTypeDescriptionManager(
+ Reference< container::XHierarchicalNameAccess > const & xTDMgr_c )
+{
+ uno::Environment curr_env(Environment::getCurrent());
+ uno::Environment target_env(CPPU_CURRENT_LANGUAGE_BINDING_NAME);
+
+ uno::Mapping curr2target(curr_env, target_env);
+
+
+ Reference<container::XHierarchicalNameAccess> xTDMgr(
+ static_cast<container::XHierarchicalNameAccess *>(
+ curr2target.mapInterface(xTDMgr_c.get(), cppu::UnoType<decltype(xTDMgr_c)>::get())),
+ SAL_NO_ACQUIRE);
+
+ Reference< lang::XComponent > xComp( xTDMgr, UNO_QUERY );
+ if (xComp.is())
+ {
+ xComp->addEventListener( new EventListenerImpl( xTDMgr ) );
+ // register c typelib callback
+ ::typelib_typedescription_registerCallback( xTDMgr.get(), typelib_callback );
+ return true;
+ }
+ return false;
+}
+
+} // end namespace cppu
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/typemanager.cxx b/cppuhelper/source/typemanager.cxx
new file mode 100644
index 000000000..bede11f7c
--- /dev/null
+++ b/cppuhelper/source/typemanager.cxx
@@ -0,0 +1,2302 @@
+/* -*- 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 <cassert>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <mutex>
+#include <set>
+#include <stack>
+#include <string_view>
+#include <utility>
+#include <vector>
+
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/reflection/NoSuchTypeNameException.hpp>
+#include <com/sun/star/reflection/TypeDescriptionSearchDepth.hpp>
+#include <com/sun/star/reflection/XConstantTypeDescription.hpp>
+#include <com/sun/star/reflection/XConstantsTypeDescription.hpp>
+#include <com/sun/star/reflection/XEnumTypeDescription.hpp>
+#include <com/sun/star/reflection/XIndirectTypeDescription.hpp>
+#include <com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp>
+#include <com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp>
+#include <com/sun/star/reflection/XInterfaceTypeDescription2.hpp>
+#include <com/sun/star/reflection/XModuleTypeDescription.hpp>
+#include <com/sun/star/reflection/XPublished.hpp>
+#include <com/sun/star/reflection/XServiceTypeDescription2.hpp>
+#include <com/sun/star/reflection/XSingletonTypeDescription2.hpp>
+#include <com/sun/star/reflection/XStructTypeDescription.hpp>
+#include <com/sun/star/reflection/XTypeDescription.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/DeploymentException.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Type.hxx>
+#include <com/sun/star/uno/TypeClass.hpp>
+#include <cppu/unotype.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <osl/file.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+#include <sal/macros.h>
+#include <sal/types.h>
+#include <o3tl/string_view.hxx>
+
+#include <unoidl/unoidl.hxx>
+
+#include "paths.hxx"
+#include "typemanager.hxx"
+
+namespace {
+
+OUString makePrefix(OUString const & name) {
+ return name.isEmpty() ? name : name + ".";
+}
+
+css::uno::Any resolveTypedefs(css::uno::Any const & type) {
+ for (css::uno::Any t(type);;) {
+ css::uno::Reference< css::reflection::XIndirectTypeDescription > ind(
+ type, css::uno::UNO_QUERY);
+ if (!ind.is() || ind->getTypeClass() != css::uno::TypeClass_TYPEDEF) {
+ return t;
+ }
+ t <<= ind->getReferencedType();
+ }
+}
+
+class SimpleTypeDescription:
+ public cppu::WeakImplHelper< css::reflection::XTypeDescription >
+{
+public:
+ SimpleTypeDescription(
+ css::uno::TypeClass typeClass, OUString name):
+ typeClass_(typeClass), name_(std::move(name))
+ {}
+
+private:
+ virtual ~SimpleTypeDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return typeClass_; }
+
+ virtual OUString SAL_CALL getName() override
+ { return name_; }
+
+ css::uno::TypeClass typeClass_;
+ OUString name_;
+};
+
+class SequenceTypeDescription:
+ public cppu::WeakImplHelper< css::reflection::XIndirectTypeDescription >
+{
+public:
+ SequenceTypeDescription(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ OUString name, OUString componentType):
+ manager_(manager), name_(std::move(name)), componentType_(std::move(componentType))
+ { assert(manager.is()); }
+
+private:
+ virtual ~SequenceTypeDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_SEQUENCE; }
+
+ virtual OUString SAL_CALL getName() override
+ { return name_; }
+
+ virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL
+ getReferencedType() override
+ { return manager_->resolve(componentType_); }
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ OUString name_;
+ OUString componentType_;
+};
+
+class PublishableDescription:
+ public cppu::WeakImplHelper< css::reflection::XPublished >
+{
+protected:
+ explicit PublishableDescription(bool published): published_(published) {}
+
+ virtual ~PublishableDescription() override {}
+
+private:
+ virtual sal_Bool SAL_CALL isPublished() override
+ { return published_; }
+
+ bool published_;
+};
+
+class ModuleDescription:
+ public cppu::WeakImplHelper< css::reflection::XModuleTypeDescription >
+{
+public:
+ ModuleDescription(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ OUString name,
+ rtl::Reference< unoidl::ModuleEntity > const & entity):
+ manager_(manager), name_(std::move(name)), entity_(entity)
+ { assert(manager.is()); assert(entity.is()); }
+
+private:
+ virtual ~ModuleDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_MODULE; }
+
+ virtual OUString SAL_CALL getName() override
+ { return name_; }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > >
+ SAL_CALL getMembers() override;
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ OUString name_;
+ rtl::Reference< unoidl::ModuleEntity > entity_;
+};
+
+css::uno::Sequence< css::uno::Reference< css::reflection::XTypeDescription > >
+ModuleDescription::getMembers() {
+ try {
+ std::vector< OUString > names(entity_->getMemberNames());
+ assert(names.size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(names.size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = manager_->resolve(makePrefix(name_) + names[i]);
+ }
+ return s;
+ } catch (unoidl::FileFormatException & e) {
+ throw css::uno::DeploymentException(
+ e.getUri() + ": " + e.getDetail(),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+}
+
+typedef cppu::ImplInheritanceHelper<
+ PublishableDescription, css::reflection::XEnumTypeDescription >
+EnumTypeDescription_Base;
+
+class EnumTypeDescription: public EnumTypeDescription_Base {
+public:
+ EnumTypeDescription(
+ OUString name,
+ rtl::Reference< unoidl::EnumTypeEntity > const & entity):
+ EnumTypeDescription_Base(entity->isPublished()), name_(std::move(name)),
+ entity_(entity)
+ { assert(entity.is()); }
+
+private:
+ virtual ~EnumTypeDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_ENUM; }
+
+ virtual OUString SAL_CALL getName() override
+ { return name_; }
+
+ virtual sal_Int32 SAL_CALL getDefaultEnumValue() override
+ { return entity_->getMembers()[0].value; }
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getEnumNames() override;
+
+ virtual css::uno::Sequence< sal_Int32 > SAL_CALL getEnumValues() override;
+
+ OUString name_;
+ rtl::Reference< unoidl::EnumTypeEntity > entity_;
+};
+
+css::uno::Sequence< OUString > EnumTypeDescription::getEnumNames()
+{
+ assert(entity_->getMembers().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(entity_->getMembers().size());
+ css::uno::Sequence< OUString > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = entity_->getMembers()[i].name;
+ }
+ return s;
+}
+
+css::uno::Sequence< sal_Int32 > EnumTypeDescription::getEnumValues()
+{
+ assert(entity_->getMembers().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(entity_->getMembers().size());
+ css::uno::Sequence< sal_Int32 > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = entity_->getMembers()[i].value;
+ }
+ return s;
+}
+
+typedef cppu::ImplInheritanceHelper<
+ PublishableDescription, css::reflection::XStructTypeDescription >
+PlainStructTypeDescription_Base;
+
+class PlainStructTypeDescription: public PlainStructTypeDescription_Base {
+public:
+ PlainStructTypeDescription(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ OUString name,
+ rtl::Reference< unoidl::PlainStructTypeEntity > const & entity):
+ PlainStructTypeDescription_Base(entity->isPublished()),
+ manager_(manager), name_(std::move(name)), entity_(entity)
+ { assert(manager.is()); assert(entity.is()); }
+
+private:
+ virtual ~PlainStructTypeDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_STRUCT; }
+
+ virtual OUString SAL_CALL getName() override
+ { return name_; }
+
+ virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL
+ getBaseType() override {
+ return entity_->getDirectBase().isEmpty()
+ ? css::uno::Reference< css::reflection::XTypeDescription >()
+ : manager_->resolve(entity_->getDirectBase());
+ }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > >
+ SAL_CALL getMemberTypes() override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getMemberNames() override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getTypeParameters() override
+ { return css::uno::Sequence< OUString >(); }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > >
+ SAL_CALL getTypeArguments() override {
+ return css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > >();
+ }
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ OUString name_;
+ rtl::Reference< unoidl::PlainStructTypeEntity > entity_;
+};
+
+css::uno::Sequence< css::uno::Reference< css::reflection::XTypeDescription > >
+PlainStructTypeDescription::getMemberTypes()
+{
+ assert(entity_->getDirectMembers().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(entity_->getDirectMembers().size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = manager_->resolve(entity_->getDirectMembers()[i].type);
+ }
+ return s;
+}
+
+css::uno::Sequence< OUString > PlainStructTypeDescription::getMemberNames()
+{
+ assert(entity_->getDirectMembers().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(entity_->getDirectMembers().size());
+ css::uno::Sequence< OUString > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = entity_->getDirectMembers()[i].name;
+ }
+ return s;
+}
+
+class ParameterizedMemberTypeDescription:
+ public cppu::WeakImplHelper< css::reflection::XTypeDescription >
+{
+public:
+ explicit ParameterizedMemberTypeDescription(
+ OUString typeParameterName):
+ typeParameterName_(std::move(typeParameterName))
+ {}
+
+private:
+ virtual ~ParameterizedMemberTypeDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_UNKNOWN; }
+
+ virtual OUString SAL_CALL getName() override
+ { return typeParameterName_; }
+
+ OUString typeParameterName_;
+};
+
+typedef cppu::ImplInheritanceHelper<
+ PublishableDescription, css::reflection::XStructTypeDescription >
+PolymorphicStructTypeTemplateDescription_Base;
+
+class PolymorphicStructTypeTemplateDescription:
+ public PolymorphicStructTypeTemplateDescription_Base
+{
+public:
+ PolymorphicStructTypeTemplateDescription(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ OUString name,
+ rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > const &
+ entity):
+ PolymorphicStructTypeTemplateDescription_Base(entity->isPublished()),
+ manager_(manager), name_(std::move(name)), entity_(entity)
+ { assert(manager.is()); assert(entity.is()); }
+
+private:
+ virtual ~PolymorphicStructTypeTemplateDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_STRUCT; }
+
+ virtual OUString SAL_CALL getName() override
+ { return name_; }
+
+ virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL
+ getBaseType() override
+ { return css::uno::Reference< css::reflection::XTypeDescription >(); }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > >
+ SAL_CALL getMemberTypes() override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getMemberNames() override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getTypeParameters() override;
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > >
+ SAL_CALL getTypeArguments() override {
+ return css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > >();
+ }
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ OUString name_;
+ rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > entity_;
+};
+
+css::uno::Sequence< css::uno::Reference< css::reflection::XTypeDescription > >
+PolymorphicStructTypeTemplateDescription::getMemberTypes()
+{
+ assert(entity_->getMembers().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(entity_->getMembers().size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = entity_->getMembers()[i].parameterized
+ ? new ParameterizedMemberTypeDescription(
+ entity_->getMembers()[i].type)
+ : manager_->resolve(entity_->getMembers()[i].type);
+ }
+ return s;
+}
+
+css::uno::Sequence< OUString >
+PolymorphicStructTypeTemplateDescription::getMemberNames()
+{
+ assert(entity_->getMembers().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(entity_->getMembers().size());
+ css::uno::Sequence< OUString > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = entity_->getMembers()[i].name;
+ }
+ return s;
+}
+
+css::uno::Sequence< OUString >
+PolymorphicStructTypeTemplateDescription::getTypeParameters()
+{
+ assert(entity_->getTypeParameters().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(entity_->getTypeParameters().size());
+ css::uno::Sequence< OUString > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = entity_->getTypeParameters()[i];
+ }
+ return s;
+}
+
+class InstantiatedPolymorphicStructTypeDescription:
+ public cppu::WeakImplHelper< css::reflection::XStructTypeDescription >
+{
+public:
+ InstantiatedPolymorphicStructTypeDescription(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ OUString name,
+ rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > const &
+ entity,
+ std::vector< OUString >&& arguments):
+ manager_(manager), name_(std::move(name)), entity_(entity), arguments_(std::move(arguments))
+ {
+ assert(manager.is());
+ assert(entity.is());
+ assert(arguments_.size() == entity->getTypeParameters().size());
+ }
+
+private:
+ virtual ~InstantiatedPolymorphicStructTypeDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_STRUCT; }
+
+ virtual OUString SAL_CALL getName() override
+ { return name_; }
+
+ virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL
+ getBaseType() override
+ { return css::uno::Reference< css::reflection::XTypeDescription >(); }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > >
+ SAL_CALL getMemberTypes() override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getMemberNames() override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getTypeParameters() override
+ { return css::uno::Sequence< OUString >(); }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > >
+ SAL_CALL getTypeArguments() override;
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ OUString name_;
+ rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > entity_;
+ std::vector< OUString > arguments_;
+};
+
+css::uno::Sequence< css::uno::Reference< css::reflection::XTypeDescription > >
+InstantiatedPolymorphicStructTypeDescription::getMemberTypes()
+{
+ assert(entity_->getMembers().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(entity_->getMembers().size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ OUString type(entity_->getMembers()[i].type);
+ if (entity_->getMembers()[i].parameterized) {
+ auto j = std::find(entity_->getTypeParameters().begin(), entity_->getTypeParameters().end(), type);
+ if (j != entity_->getTypeParameters().end()) {
+ type = arguments_[j - entity_->getTypeParameters().begin()];
+ goto found;
+ }
+ assert(false); // this cannot happen //TODO!
+ found:;
+ }
+ r[i] = manager_->resolve(type);
+ }
+ return s;
+}
+
+css::uno::Sequence< OUString >
+InstantiatedPolymorphicStructTypeDescription::getMemberNames()
+{
+ assert(entity_->getMembers().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(entity_->getMembers().size());
+ css::uno::Sequence< OUString > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = entity_->getMembers()[i].name;
+ }
+ return s;
+}
+css::uno::Sequence< css::uno::Reference< css::reflection::XTypeDescription > >
+InstantiatedPolymorphicStructTypeDescription::getTypeArguments()
+{
+ assert(arguments_.size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(arguments_.size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = manager_->resolve(arguments_[i]);
+ }
+ return s;
+}
+
+typedef cppu::ImplInheritanceHelper<
+ PublishableDescription, css::reflection::XCompoundTypeDescription >
+ExceptionTypeDescription_Base;
+
+class ExceptionTypeDescription: public ExceptionTypeDescription_Base {
+public:
+ ExceptionTypeDescription(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ OUString name,
+ rtl::Reference< unoidl::ExceptionTypeEntity > const & entity):
+ ExceptionTypeDescription_Base(entity->isPublished()), manager_(manager),
+ name_(std::move(name)), entity_(entity)
+ { assert(manager.is()); assert(entity.is()); }
+
+private:
+ virtual ~ExceptionTypeDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_EXCEPTION; }
+
+ virtual OUString SAL_CALL getName() override
+ { return name_; }
+
+ virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL
+ getBaseType() override {
+ return entity_->getDirectBase().isEmpty()
+ ? css::uno::Reference< css::reflection::XTypeDescription >()
+ : manager_->resolve(entity_->getDirectBase());
+ }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > >
+ SAL_CALL getMemberTypes() override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getMemberNames() override;
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ OUString name_;
+ rtl::Reference< unoidl::ExceptionTypeEntity > entity_;
+};
+
+css::uno::Sequence< css::uno::Reference< css::reflection::XTypeDescription > >
+ExceptionTypeDescription::getMemberTypes() {
+ assert(entity_->getDirectMembers().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(entity_->getDirectMembers().size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = manager_->resolve(entity_->getDirectMembers()[i].type);
+ }
+ return s;
+}
+
+css::uno::Sequence< OUString > ExceptionTypeDescription::getMemberNames()
+{
+ assert(entity_->getDirectMembers().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(entity_->getDirectMembers().size());
+ css::uno::Sequence< OUString > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = entity_->getDirectMembers()[i].name;
+ }
+ return s;
+}
+
+class AttributeDescription:
+ public cppu::WeakImplHelper<
+ css::reflection::XInterfaceAttributeTypeDescription2 >
+{
+public:
+ AttributeDescription(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ OUString name,
+ unoidl::InterfaceTypeEntity::Attribute attribute,
+ sal_Int32 position):
+ manager_(manager), name_(std::move(name)), attribute_(std::move(attribute)),
+ position_(position)
+ { assert(manager.is()); }
+
+private:
+ virtual ~AttributeDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_INTERFACE_ATTRIBUTE; }
+
+ virtual OUString SAL_CALL getName() override
+ { return name_; }
+
+ virtual OUString SAL_CALL getMemberName() override
+ { return attribute_.name; }
+
+ virtual sal_Int32 SAL_CALL getPosition() override
+ { return position_; }
+
+ virtual sal_Bool SAL_CALL isReadOnly() override
+ { return attribute_.readOnly; }
+
+ virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL
+ getType() override
+ { return manager_->resolve(attribute_.type); }
+
+ virtual sal_Bool SAL_CALL isBound() override
+ { return attribute_.bound; }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XCompoundTypeDescription > >
+ SAL_CALL getGetExceptions() override;
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XCompoundTypeDescription > >
+ SAL_CALL getSetExceptions() override;
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ OUString name_;
+ unoidl::InterfaceTypeEntity::Attribute attribute_;
+ sal_Int32 position_;
+};
+
+css::uno::Sequence<
+ css::uno::Reference< css::reflection::XCompoundTypeDescription > >
+AttributeDescription::getGetExceptions() {
+ assert(attribute_.getExceptions.size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(attribute_.getExceptions.size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XCompoundTypeDescription > > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i].set(
+ manager_->resolve(attribute_.getExceptions[i]),
+ css::uno::UNO_QUERY_THROW);
+ }
+ return s;
+}
+
+css::uno::Sequence<
+ css::uno::Reference< css::reflection::XCompoundTypeDescription > >
+AttributeDescription::getSetExceptions() {
+ assert(attribute_.setExceptions.size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(attribute_.setExceptions.size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XCompoundTypeDescription > > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i].set(
+ manager_->resolve(attribute_.setExceptions[i]),
+ css::uno::UNO_QUERY_THROW);
+ }
+ return s;
+}
+
+class MethodParameter:
+ public cppu::WeakImplHelper< css::reflection::XMethodParameter >
+{
+public:
+ MethodParameter(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ unoidl::InterfaceTypeEntity::Method::Parameter parameter,
+ sal_Int32 position):
+ manager_(manager), parameter_(std::move(parameter)), position_(position)
+ { assert(manager.is()); }
+
+private:
+ virtual ~MethodParameter() override {}
+
+ virtual OUString SAL_CALL getName() override
+ { return parameter_.name; }
+
+ virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL
+ getType() override
+ { return manager_->resolve(parameter_.type); }
+
+ virtual sal_Bool SAL_CALL isIn() override {
+ return
+ (parameter_.direction
+ == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN)
+ || (parameter_.direction
+ == unoidl::InterfaceTypeEntity::Method::Parameter::
+ DIRECTION_IN_OUT);
+ }
+
+ virtual sal_Bool SAL_CALL isOut() override {
+ return
+ (parameter_.direction
+ == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT)
+ || (parameter_.direction
+ == unoidl::InterfaceTypeEntity::Method::Parameter::
+ DIRECTION_IN_OUT);
+ }
+
+ virtual sal_Int32 SAL_CALL getPosition() override
+ { return position_; }
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ unoidl::InterfaceTypeEntity::Method::Parameter parameter_;
+ sal_Int32 position_;
+};
+
+class MethodDescription:
+ public cppu::WeakImplHelper<
+ css::reflection::XInterfaceMethodTypeDescription >
+{
+public:
+ MethodDescription(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ OUString name,
+ unoidl::InterfaceTypeEntity::Method method, sal_Int32 position):
+ manager_(manager), name_(std::move(name)), method_(std::move(method)), position_(position)
+ { assert(manager.is()); }
+
+private:
+ virtual ~MethodDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_INTERFACE_METHOD; }
+
+ virtual OUString SAL_CALL getName() override
+ { return name_; }
+
+ virtual OUString SAL_CALL getMemberName() override
+ { return method_.name; }
+
+ virtual sal_Int32 SAL_CALL getPosition() override
+ { return position_; }
+
+ virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL
+ getReturnType() override
+ { return manager_->resolve(method_.returnType); }
+
+ virtual sal_Bool SAL_CALL isOneway() override
+ { return false; }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XMethodParameter > >
+ SAL_CALL getParameters() override;
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > >
+ SAL_CALL getExceptions() override;
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ OUString name_;
+ unoidl::InterfaceTypeEntity::Method method_;
+ sal_Int32 position_;
+};
+
+css::uno::Sequence< css::uno::Reference< css::reflection::XMethodParameter > >
+MethodDescription::getParameters() {
+ assert(method_.parameters.size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(method_.parameters.size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XMethodParameter > > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = new MethodParameter(manager_, method_.parameters[i], i);
+ }
+ return s;
+}
+
+css::uno::Sequence< css::uno::Reference< css::reflection::XTypeDescription > >
+MethodDescription::getExceptions() {
+ assert(method_.exceptions.size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(method_.exceptions.size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = manager_->resolve(method_.exceptions[i]);
+ }
+ return s;
+}
+
+class BaseOffset {
+public:
+ explicit BaseOffset(
+ css::uno::Reference< css::reflection::XInterfaceTypeDescription2 >
+ const & description);
+
+ BaseOffset(const BaseOffset&) = delete;
+ const BaseOffset& operator=(const BaseOffset&) = delete;
+
+ sal_Int32 get() const { return offset_; }
+
+private:
+ void calculateBases(
+ css::uno::Reference< css::reflection::XInterfaceTypeDescription2 >
+ const & description);
+
+ void calculate(
+ css::uno::Reference< css::reflection::XInterfaceTypeDescription2 >
+ const & description);
+
+ std::set< OUString > set_;
+ sal_Int32 offset_;
+};
+
+BaseOffset::BaseOffset(
+ css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > const &
+ description):
+ offset_(0)
+{
+ calculateBases(description);
+}
+
+void BaseOffset::calculateBases(
+ css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > const &
+ description)
+{
+ const css::uno::Sequence<
+ css::uno::Reference < css::reflection::XTypeDescription > > bases(
+ description->getBaseTypes());
+ for (const auto & i : bases) {
+ calculate(
+ css::uno::Reference< css::reflection::XInterfaceTypeDescription2 >(
+ resolveTypedefs(css::uno::Any(i)),
+ css::uno::UNO_QUERY_THROW));
+ }
+}
+
+void BaseOffset::calculate(
+ css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > const &
+ description)
+{
+ if (set_.insert(description->getName()).second) {
+ calculateBases(description);
+ offset_ += description->getMembers().getLength();
+ }
+}
+
+typedef cppu::ImplInheritanceHelper<
+ PublishableDescription, css::reflection::XInterfaceTypeDescription2 >
+InterfaceTypeDescription_Base;
+
+class InterfaceTypeDescription: public InterfaceTypeDescription_Base {
+public:
+ InterfaceTypeDescription(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ OUString name,
+ rtl::Reference< unoidl::InterfaceTypeEntity > const & entity):
+ InterfaceTypeDescription_Base(entity->isPublished()), manager_(manager),
+ name_(std::move(name)), entity_(entity)
+ { assert(manager.is()); assert(entity.is()); }
+
+private:
+ virtual ~InterfaceTypeDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_INTERFACE; }
+
+ virtual OUString SAL_CALL getName() override
+ { return name_; }
+
+ virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL
+ getBaseType() override {
+ return entity_->getDirectMandatoryBases().empty()
+ ? css::uno::Reference< css::reflection::XTypeDescription >()
+ : manager_->resolve(entity_->getDirectMandatoryBases()[0].name);
+ }
+
+ virtual css::uno::Uik SAL_CALL getUik() override
+ { return css::uno::Uik(); }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference<
+ css::reflection::XInterfaceMemberTypeDescription > >
+ SAL_CALL getMembers() override;
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > >
+ SAL_CALL getBaseTypes() override;
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > >
+ SAL_CALL getOptionalBaseTypes() override;
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ OUString name_;
+ rtl::Reference< unoidl::InterfaceTypeEntity > entity_;
+};
+
+css::uno::Sequence<
+ css::uno::Reference< css::reflection::XInterfaceMemberTypeDescription > >
+InterfaceTypeDescription::getMembers() {
+ assert(
+ entity_->getDirectAttributes().size() <= SAL_MAX_INT32
+ && (entity_->getDirectMethods().size()
+ <= SAL_MAX_INT32 - entity_->getDirectAttributes().size()));
+ sal_Int32 n1 = static_cast< sal_Int32 >(
+ entity_->getDirectAttributes().size());
+ sal_Int32 n2 = static_cast< sal_Int32 >(entity_->getDirectMethods().size());
+ css::uno::Sequence<
+ css::uno::Reference<
+ css::reflection::XInterfaceMemberTypeDescription > > s(n1 + n2);
+ auto r = asNonConstRange(s);
+ sal_Int32 off = BaseOffset(this).get();
+ for (sal_Int32 i = 0; i != n1; ++i) {
+ r[i] = new AttributeDescription(
+ manager_, name_ + "::" + entity_->getDirectAttributes()[i].name,
+ entity_->getDirectAttributes()[i], off + i);
+ }
+ for (sal_Int32 i = 0; i != n2; ++i) {
+ r[n1 + i] = new MethodDescription(
+ manager_, name_ + "::" + entity_->getDirectMethods()[i].name,
+ entity_->getDirectMethods()[i], off + n1 + i);
+ }
+ return s;
+}
+
+css::uno::Sequence< css::uno::Reference< css::reflection::XTypeDescription > >
+InterfaceTypeDescription::getBaseTypes() {
+ assert(entity_->getDirectMandatoryBases().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(
+ entity_->getDirectMandatoryBases().size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = manager_->resolve(entity_->getDirectMandatoryBases()[i].name);
+ }
+ return s;
+}
+
+css::uno::Sequence< css::uno::Reference< css::reflection::XTypeDescription > >
+InterfaceTypeDescription::getOptionalBaseTypes()
+{
+ assert(entity_->getDirectOptionalBases().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(
+ entity_->getDirectOptionalBases().size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XTypeDescription > > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = manager_->resolve(entity_->getDirectOptionalBases()[i].name);
+ }
+ return s;
+}
+
+class ConstantDescription:
+ public cppu::WeakImplHelper< css::reflection::XConstantTypeDescription >
+{
+public:
+ ConstantDescription(
+ OUString const & constantGroupName,
+ unoidl::ConstantGroupEntity::Member const & member);
+
+private:
+ virtual ~ConstantDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_CONSTANT; }
+
+ virtual OUString SAL_CALL getName() override
+ { return name_; }
+
+ virtual css::uno::Any SAL_CALL getConstantValue() override
+ { return value_; }
+
+ OUString name_;
+ css::uno::Any value_;
+};
+
+ConstantDescription::ConstantDescription(
+ OUString const & constantGroupName,
+ unoidl::ConstantGroupEntity::Member const & member):
+ name_(makePrefix(constantGroupName) + member.name)
+{
+ switch (member.value.type) {
+ case unoidl::ConstantValue::TYPE_BOOLEAN:
+ value_ <<= member.value.booleanValue;
+ break;
+ case unoidl::ConstantValue::TYPE_BYTE:
+ value_ <<= member.value.byteValue;
+ break;
+ case unoidl::ConstantValue::TYPE_SHORT:
+ value_ <<= member.value.shortValue;
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
+ value_ <<= member.value.unsignedShortValue;
+ break;
+ case unoidl::ConstantValue::TYPE_LONG:
+ value_ <<= member.value.longValue;
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
+ value_ <<= member.value.unsignedLongValue;
+ break;
+ case unoidl::ConstantValue::TYPE_HYPER:
+ value_ <<= member.value.hyperValue;
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
+ value_ <<= member.value.unsignedHyperValue;
+ break;
+ case unoidl::ConstantValue::TYPE_FLOAT:
+ value_ <<= member.value.floatValue;
+ break;
+ case unoidl::ConstantValue::TYPE_DOUBLE:
+ value_ <<= member.value.doubleValue;
+ break;
+ default:
+ for (;;) { std::abort(); } // this cannot happen
+ }
+}
+
+typedef cppu::ImplInheritanceHelper<
+ PublishableDescription, css::reflection::XConstantsTypeDescription >
+ConstantGroupDescription_Base;
+
+class ConstantGroupDescription: public ConstantGroupDescription_Base {
+public:
+ ConstantGroupDescription(
+ OUString name,
+ rtl::Reference< unoidl::ConstantGroupEntity > const & entity):
+ ConstantGroupDescription_Base(entity->isPublished()), name_(std::move(name)),
+ entity_(entity)
+ { assert(entity.is()); }
+
+private:
+ virtual ~ConstantGroupDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_CONSTANTS; }
+
+ virtual OUString SAL_CALL getName() override
+ { return name_; }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XConstantTypeDescription > >
+ SAL_CALL getConstants() override;
+
+ OUString name_;
+ rtl::Reference< unoidl::ConstantGroupEntity > entity_;
+};
+
+css::uno::Sequence<
+ css::uno::Reference< css::reflection::XConstantTypeDescription > >
+ConstantGroupDescription::getConstants() {
+ assert(entity_->getMembers().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(entity_->getMembers().size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XConstantTypeDescription > > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = new ConstantDescription(name_, entity_->getMembers()[i]);
+ }
+ return s;
+}
+
+typedef cppu::ImplInheritanceHelper<
+ PublishableDescription, css::reflection::XIndirectTypeDescription >
+TypedefDescription_Base;
+
+class TypedefDescription: public TypedefDescription_Base {
+public:
+ TypedefDescription(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ OUString name,
+ rtl::Reference< unoidl::TypedefEntity > const & entity):
+ TypedefDescription_Base(entity->isPublished()), manager_(manager),
+ name_(std::move(name)), entity_(entity)
+ { assert(manager.is()); assert(entity.is()); }
+
+private:
+ virtual ~TypedefDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_TYPEDEF; }
+
+ virtual OUString SAL_CALL getName() override
+ { return name_; }
+
+ virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL
+ getReferencedType() override
+ { return manager_->resolve(entity_->getType()); }
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ OUString name_;
+ rtl::Reference< unoidl::TypedefEntity > entity_;
+};
+
+class ConstructorParameter:
+ public cppu::WeakImplHelper< css::reflection::XParameter >
+{
+public:
+ ConstructorParameter(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter parameter,
+ sal_Int32 position):
+ manager_(manager), parameter_(std::move(parameter)), position_(position)
+ { assert(manager.is()); }
+
+private:
+ virtual ~ConstructorParameter() override {}
+
+ virtual OUString SAL_CALL getName() override
+ { return parameter_.name; }
+
+ virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL
+ getType() override
+ { return manager_->resolve(parameter_.type); }
+
+ virtual sal_Bool SAL_CALL isIn() override
+ { return true; }
+
+ virtual sal_Bool SAL_CALL isOut() override
+ { return false; }
+
+ virtual sal_Int32 SAL_CALL getPosition() override
+ { return position_; }
+
+ virtual sal_Bool SAL_CALL isRestParameter() override
+ { return parameter_.rest; }
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter
+ parameter_;
+ sal_Int32 position_;
+};
+
+class ConstructorDescription:
+ public cppu::WeakImplHelper<
+ css::reflection::XServiceConstructorDescription >
+{
+public:
+ ConstructorDescription(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ unoidl::SingleInterfaceBasedServiceEntity::Constructor constructor):
+ manager_(manager), constructor_(std::move(constructor))
+ { assert(manager.is()); }
+
+private:
+ virtual ~ConstructorDescription() override {}
+
+ virtual sal_Bool SAL_CALL isDefaultConstructor() override
+ { return constructor_.defaultConstructor; }
+
+ virtual OUString SAL_CALL getName() override
+ { return constructor_.name; }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XParameter > >
+ SAL_CALL getParameters() override;
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XCompoundTypeDescription > >
+ SAL_CALL getExceptions() override;
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ unoidl::SingleInterfaceBasedServiceEntity::Constructor constructor_;
+};
+
+css::uno::Sequence< css::uno::Reference< css::reflection::XParameter > >
+ConstructorDescription::getParameters() {
+ assert(constructor_.parameters.size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(constructor_.parameters.size());
+ css::uno::Sequence< css::uno::Reference< css::reflection::XParameter > > s(
+ n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = new ConstructorParameter(
+ manager_, constructor_.parameters[i], i);
+ }
+ return s;
+}
+
+css::uno::Sequence<
+ css::uno::Reference< css::reflection::XCompoundTypeDescription > >
+ConstructorDescription::getExceptions() {
+ assert(constructor_.exceptions.size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(constructor_.exceptions.size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XCompoundTypeDescription > > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i].set(
+ manager_->resolve(constructor_.exceptions[i]),
+ css::uno::UNO_QUERY_THROW);
+ }
+ return s;
+}
+
+typedef cppu::ImplInheritanceHelper<
+ PublishableDescription, css::reflection::XServiceTypeDescription2 >
+SingleInterfaceBasedServiceDescription_Base;
+
+class SingleInterfaceBasedServiceDescription:
+ public SingleInterfaceBasedServiceDescription_Base
+{
+public:
+ SingleInterfaceBasedServiceDescription(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ OUString name,
+ rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > const &
+ entity):
+ SingleInterfaceBasedServiceDescription_Base(entity->isPublished()),
+ manager_(manager), name_(std::move(name)), entity_(entity)
+ { assert(manager.is()); assert(entity.is()); }
+
+private:
+ virtual ~SingleInterfaceBasedServiceDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_SERVICE; }
+
+ virtual OUString SAL_CALL getName() override
+ { return name_; }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XServiceTypeDescription > >
+ SAL_CALL getMandatoryServices() override
+ {
+ return css::uno::Sequence<
+ css::uno::Reference< css::reflection::XServiceTypeDescription > >();
+ }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XServiceTypeDescription > >
+ SAL_CALL getOptionalServices() override
+ {
+ return css::uno::Sequence<
+ css::uno::Reference< css::reflection::XServiceTypeDescription > >();
+ }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XInterfaceTypeDescription > >
+ SAL_CALL getMandatoryInterfaces() override
+ {
+ return css::uno::Sequence<
+ css::uno::Reference<
+ css::reflection::XInterfaceTypeDescription > >();
+ }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XInterfaceTypeDescription > >
+ SAL_CALL getOptionalInterfaces() override
+ {
+ return css::uno::Sequence<
+ css::uno::Reference<
+ css::reflection::XInterfaceTypeDescription > >();
+ }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XPropertyTypeDescription > >
+ SAL_CALL getProperties() override
+ {
+ return css::uno::Sequence<
+ css::uno::Reference<
+ css::reflection::XPropertyTypeDescription > >();
+ }
+
+ virtual sal_Bool SAL_CALL isSingleInterfaceBased() override
+ { return true; }
+
+ virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL
+ getInterface() override
+ { return manager_->resolve(entity_->getBase()); }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XServiceConstructorDescription > >
+ SAL_CALL getConstructors() override;
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ OUString name_;
+ rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > entity_;
+};
+
+css::uno::Sequence<
+ css::uno::Reference< css::reflection::XServiceConstructorDescription > >
+SingleInterfaceBasedServiceDescription::getConstructors()
+{
+ assert(entity_->getConstructors().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(entity_->getConstructors().size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XServiceConstructorDescription > >
+ s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = new ConstructorDescription(
+ manager_, entity_->getConstructors()[i]);
+ }
+ return s;
+}
+
+class PropertyDescription:
+ public cppu::WeakImplHelper< css::reflection::XPropertyTypeDescription >
+{
+public:
+ PropertyDescription(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ unoidl::AccumulationBasedServiceEntity::Property property):
+ manager_(manager), property_(std::move(property))
+ { assert(manager.is()); }
+
+private:
+ virtual ~PropertyDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_PROPERTY; }
+
+ virtual OUString SAL_CALL getName() override
+ { return property_.name; }
+
+ virtual sal_Int16 SAL_CALL getPropertyFlags() override
+ { return property_.attributes; }
+
+ virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL
+ getPropertyTypeDescription() override
+ { return manager_->resolve(property_.type); }
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ unoidl::AccumulationBasedServiceEntity::Property property_;
+};
+
+typedef cppu::ImplInheritanceHelper<
+ PublishableDescription, css::reflection::XServiceTypeDescription2 >
+AccumulationBasedServiceDescription_Base;
+
+class AccumulationBasedServiceDescription:
+ public AccumulationBasedServiceDescription_Base
+{
+public:
+ AccumulationBasedServiceDescription(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ OUString name,
+ rtl::Reference< unoidl::AccumulationBasedServiceEntity > const &
+ entity):
+ AccumulationBasedServiceDescription_Base(entity->isPublished()),
+ manager_(manager), name_(std::move(name)), entity_(entity)
+ { assert(manager.is()); assert(entity.is()); }
+
+private:
+ virtual ~AccumulationBasedServiceDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_SERVICE; }
+
+ virtual OUString SAL_CALL getName() override
+ { return name_; }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XServiceTypeDescription > >
+ SAL_CALL getMandatoryServices() override;
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XServiceTypeDescription > >
+ SAL_CALL getOptionalServices() override;
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XInterfaceTypeDescription > >
+ SAL_CALL getMandatoryInterfaces() override;
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XInterfaceTypeDescription > >
+ SAL_CALL getOptionalInterfaces() override;
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XPropertyTypeDescription > >
+ SAL_CALL getProperties() override;
+
+ virtual sal_Bool SAL_CALL isSingleInterfaceBased() override
+ { return false; }
+
+ virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL
+ getInterface() override
+ { return css::uno::Reference< css::reflection::XTypeDescription >(); }
+
+ virtual
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XServiceConstructorDescription > >
+ SAL_CALL getConstructors() override
+ {
+ return css::uno::Sequence<
+ css::uno::Reference<
+ css::reflection::XServiceConstructorDescription > >();
+ }
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ OUString name_;
+ rtl::Reference< unoidl::AccumulationBasedServiceEntity > entity_;
+};
+
+css::uno::Sequence<
+ css::uno::Reference< css::reflection::XServiceTypeDescription > >
+AccumulationBasedServiceDescription::getMandatoryServices()
+{
+ assert(entity_->getDirectMandatoryBaseServices().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(
+ entity_->getDirectMandatoryBaseServices().size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XServiceTypeDescription > > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i].set(
+ manager_->resolve(
+ entity_->getDirectMandatoryBaseServices()[i].name),
+ css::uno::UNO_QUERY_THROW);
+ }
+ return s;
+}
+
+css::uno::Sequence<
+ css::uno::Reference< css::reflection::XServiceTypeDescription > >
+AccumulationBasedServiceDescription::getOptionalServices()
+{
+ assert(entity_->getDirectOptionalBaseServices().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(
+ entity_->getDirectOptionalBaseServices().size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XServiceTypeDescription > > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i].set(
+ manager_->resolve(entity_->getDirectOptionalBaseServices()[i].name),
+ css::uno::UNO_QUERY_THROW);
+ }
+ return s;
+}
+
+css::uno::Sequence<
+ css::uno::Reference< css::reflection::XInterfaceTypeDescription > >
+AccumulationBasedServiceDescription::getMandatoryInterfaces()
+{
+ assert(entity_->getDirectMandatoryBaseInterfaces().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(
+ entity_->getDirectMandatoryBaseInterfaces().size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XInterfaceTypeDescription > > s(
+ n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i].set(
+ resolveTypedefs(
+ manager_->find(
+ entity_->getDirectMandatoryBaseInterfaces()[i].name)),
+ css::uno::UNO_QUERY_THROW);
+ }
+ return s;
+}
+
+css::uno::Sequence<
+ css::uno::Reference< css::reflection::XInterfaceTypeDescription > >
+AccumulationBasedServiceDescription::getOptionalInterfaces()
+{
+ assert(entity_->getDirectOptionalBaseInterfaces().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(
+ entity_->getDirectOptionalBaseInterfaces().size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XInterfaceTypeDescription > > s(
+ n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i].set(
+ resolveTypedefs(
+ manager_->find(
+ entity_->getDirectOptionalBaseInterfaces()[i].name)),
+ css::uno::UNO_QUERY_THROW);
+ }
+ return s;
+}
+
+css::uno::Sequence<
+ css::uno::Reference< css::reflection::XPropertyTypeDescription > >
+AccumulationBasedServiceDescription::getProperties()
+{
+ assert(entity_->getDirectProperties().size() <= SAL_MAX_INT32);
+ sal_Int32 n = static_cast< sal_Int32 >(
+ entity_->getDirectProperties().size());
+ css::uno::Sequence<
+ css::uno::Reference< css::reflection::XPropertyTypeDescription > > s(n);
+ auto r = asNonConstRange(s);
+ for (sal_Int32 i = 0; i != n; ++i) {
+ r[i] = new PropertyDescription(
+ manager_, entity_->getDirectProperties()[i]);
+ }
+ return s;
+}
+
+typedef cppu::ImplInheritanceHelper<
+ PublishableDescription, css::reflection::XSingletonTypeDescription2 >
+InterfaceBasedSingletonDescription_Base;
+
+class InterfaceBasedSingletonDescription:
+ public InterfaceBasedSingletonDescription_Base
+{
+public:
+ InterfaceBasedSingletonDescription(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ OUString name,
+ rtl::Reference< unoidl::InterfaceBasedSingletonEntity > const & entity):
+ InterfaceBasedSingletonDescription_Base(entity->isPublished()),
+ manager_(manager), name_(std::move(name)), entity_(entity)
+ { assert(manager.is()); assert(entity.is()); }
+
+private:
+ virtual ~InterfaceBasedSingletonDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_SINGLETON; }
+
+ virtual OUString SAL_CALL getName() override
+ { return name_; }
+
+ virtual css::uno::Reference< css::reflection::XServiceTypeDescription >
+ SAL_CALL getService() override
+ {
+ return
+ css::uno::Reference< css::reflection::XServiceTypeDescription >();
+ }
+
+ virtual sal_Bool SAL_CALL isInterfaceBased() override
+ { return true; }
+
+ virtual css::uno::Reference< css::reflection::XTypeDescription >
+ SAL_CALL getInterface() override
+ { return manager_->resolve(entity_->getBase()); }
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ OUString name_;
+ rtl::Reference< unoidl::InterfaceBasedSingletonEntity > entity_;
+};
+
+typedef cppu::ImplInheritanceHelper<
+ PublishableDescription, css::reflection::XSingletonTypeDescription2 >
+ServiceBasedSingletonDescription_Base;
+
+class ServiceBasedSingletonDescription:
+ public ServiceBasedSingletonDescription_Base
+{
+public:
+ ServiceBasedSingletonDescription(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ OUString name,
+ rtl::Reference< unoidl::ServiceBasedSingletonEntity > const & entity):
+ ServiceBasedSingletonDescription_Base(entity->isPublished()),
+ manager_(manager), name_(std::move(name)), entity_(entity)
+ { assert(manager.is()); assert(entity.is()); }
+
+private:
+ virtual ~ServiceBasedSingletonDescription() override {}
+
+ virtual css::uno::TypeClass SAL_CALL getTypeClass() override
+ { return css::uno::TypeClass_SINGLETON; }
+
+ virtual OUString SAL_CALL getName() override
+ { return name_; }
+
+ virtual css::uno::Reference< css::reflection::XServiceTypeDescription >
+ SAL_CALL getService() override
+ {
+ return css::uno::Reference< css::reflection::XServiceTypeDescription >(
+ manager_->resolve(entity_->getBase()), css::uno::UNO_QUERY_THROW);
+ }
+
+ virtual sal_Bool SAL_CALL isInterfaceBased() override
+ { return false; }
+
+ virtual css::uno::Reference< css::reflection::XTypeDescription >
+ SAL_CALL getInterface() override
+ { return css::uno::Reference< css::reflection::XTypeDescription >(); }
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ OUString name_;
+ rtl::Reference< unoidl::ServiceBasedSingletonEntity > entity_;
+};
+
+class Enumeration:
+ public cppu::WeakImplHelper< css::reflection::XTypeDescriptionEnumeration >
+{
+public:
+ Enumeration(
+ rtl::Reference< cppuhelper::TypeManager > const & manager,
+ OUString const & prefix,
+ rtl::Reference< unoidl::MapCursor > const & cursor,
+ css::uno::Sequence< css::uno::TypeClass > const & types, bool deep):
+ manager_(manager), types_(types), deep_(deep)
+ {
+ assert(manager.is());
+ positions_.push(Position(prefix, cursor));
+ findNextMatch();
+ }
+
+private:
+ virtual ~Enumeration() override {}
+
+ virtual sal_Bool SAL_CALL hasMoreElements() override
+ { return !positions_.empty(); }
+
+ virtual css::uno::Any SAL_CALL nextElement() override
+ { return css::uno::Any(nextTypeDescription()); }
+
+ virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL
+ nextTypeDescription() override;
+
+ bool matches(css::uno::TypeClass tc) const;
+
+ void findNextMatch();
+
+ struct Position {
+ Position(
+ OUString thePrefix,
+ rtl::Reference< unoidl::MapCursor > const & theCursor):
+ prefix(std::move(thePrefix)), cursor(theCursor)
+ { assert(theCursor.is()); }
+
+ Position(
+ OUString thePrefix,
+ rtl::Reference< unoidl::ConstantGroupEntity > const &
+ theConstantGroup):
+ prefix(std::move(thePrefix)), constantGroup(theConstantGroup),
+ constantGroupIndex(constantGroup->getMembers().begin())
+ { assert(theConstantGroup.is()); }
+
+ Position(Position const & other):
+ prefix(other.prefix), cursor(other.cursor),
+ constantGroup(other.constantGroup)
+ {
+ if (constantGroup.is()) {
+ constantGroupIndex = other.constantGroupIndex;
+ }
+ }
+
+ OUString prefix;
+ rtl::Reference< unoidl::MapCursor > cursor;
+ rtl::Reference< unoidl::ConstantGroupEntity > constantGroup;
+ std::vector< unoidl::ConstantGroupEntity::Member >::const_iterator
+ constantGroupIndex;
+ };
+
+ rtl::Reference< cppuhelper::TypeManager > manager_;
+ css::uno::Sequence< css::uno::TypeClass > types_;
+ bool deep_;
+
+ std::mutex mutex_;
+ std::stack< Position, std::vector<Position> > positions_;
+ OUString current_;
+};
+
+css::uno::Reference< css::reflection::XTypeDescription >
+Enumeration::nextTypeDescription()
+{
+ OUString name;
+ {
+ std::scoped_lock g(mutex_);
+ if (positions_.empty()) {
+ throw css::container::NoSuchElementException(
+ "exhausted XTypeDescriptionEnumeration",
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ name = current_;
+ findNextMatch();
+ }
+ return manager_->resolve(name);
+}
+
+bool Enumeration::matches(css::uno::TypeClass tc) const {
+ if (!types_.hasElements()) {
+ return true;
+ }
+ for (const auto & i : types_) {
+ if (i == tc) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void Enumeration::findNextMatch() {
+ try {
+ for (;;) {
+ assert(!positions_.empty());
+ OUString name;
+ if (positions_.top().cursor.is()) { // root or module
+ rtl::Reference< unoidl::Entity > ent(
+ positions_.top().cursor->getNext(&name));
+ if (!ent.is()) {
+ positions_.pop();
+ if (positions_.empty()) {
+ break;
+ }
+ continue;
+ }
+ name = positions_.top().prefix + name;
+ css::uno::TypeClass tc;
+ switch (ent->getSort()) {
+ case unoidl::Entity::SORT_MODULE:
+ tc = css::uno::TypeClass_MODULE;
+ if (deep_) {
+ positions_.push(
+ Position(
+ makePrefix(name),
+ static_cast< unoidl::ModuleEntity * >(
+ ent.get())->createCursor()));
+ }
+ break;
+ case unoidl::Entity::SORT_ENUM_TYPE:
+ tc = css::uno::TypeClass_ENUM;
+ break;
+ case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
+ case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
+ tc = css::uno::TypeClass_STRUCT;
+ break;
+ case unoidl::Entity::SORT_EXCEPTION_TYPE:
+ tc = css::uno::TypeClass_EXCEPTION;
+ break;
+ case unoidl::Entity::SORT_INTERFACE_TYPE:
+ tc = css::uno::TypeClass_INTERFACE;
+ break;
+ case unoidl::Entity::SORT_TYPEDEF:
+ tc = css::uno::TypeClass_TYPEDEF;
+ break;
+ case unoidl::Entity::SORT_CONSTANT_GROUP:
+ tc = css::uno::TypeClass_CONSTANTS;
+ if (deep_ && matches(css::uno::TypeClass_CONSTANT)) {
+ positions_.push(
+ Position(
+ makePrefix(name),
+ static_cast< unoidl::ConstantGroupEntity * >(
+ ent.get())));
+ }
+ break;
+ case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
+ case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
+ tc = css::uno::TypeClass_SERVICE;
+ break;
+ case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
+ case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
+ tc = css::uno::TypeClass_SINGLETON;
+ break;
+ default:
+ for (;;) { std::abort(); } // this cannot happen
+ }
+ if (matches(tc)) {
+ current_ = name;
+ break;
+ }
+ } else { // constant group
+ if (positions_.top().constantGroupIndex
+ == positions_.top().constantGroup->getMembers().end())
+ {
+ positions_.pop();
+ if (positions_.empty()) {
+ break;
+ }
+ continue;
+ }
+ current_ = positions_.top().prefix
+ + positions_.top().constantGroupIndex++->name;
+ break;
+ }
+ }
+ } catch (unoidl::FileFormatException & e) {
+ throw css::uno::DeploymentException(
+ e.getUri() + ": " + e.getDetail(),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+}
+
+}
+
+cppuhelper::TypeManager::TypeManager():
+ TypeManager_Base(m_aMutex),
+ manager_(new unoidl::Manager)
+{}
+
+css::uno::Any cppuhelper::TypeManager::find(OUString const & name) {
+ //TODO: caching? (here or in unoidl::Manager?)
+ static constexpr std::pair<std::u16string_view, css::uno::TypeClass> const simple[] = {
+ { u"void", css::uno::TypeClass_VOID },
+ { u"boolean", css::uno::TypeClass_BOOLEAN },
+ { u"byte", css::uno::TypeClass_BYTE },
+ { u"short", css::uno::TypeClass_SHORT },
+ { u"unsigned short", css::uno::TypeClass_UNSIGNED_SHORT },
+ { u"long", css::uno::TypeClass_LONG },
+ { u"unsigned long", css::uno::TypeClass_UNSIGNED_LONG },
+ { u"hyper", css::uno::TypeClass_HYPER },
+ { u"unsigned hyper", css::uno::TypeClass_UNSIGNED_HYPER },
+ { u"float", css::uno::TypeClass_FLOAT },
+ { u"double", css::uno::TypeClass_DOUBLE },
+ { u"char", css::uno::TypeClass_CHAR },
+ { u"string", css::uno::TypeClass_STRING },
+ { u"type", css::uno::TypeClass_TYPE },
+ { u"any", css::uno::TypeClass_ANY } };
+ for (const auto& [ rName, rTypeClass ] : simple) {
+ if (name == rName) {
+ return css::uno::Any(
+ css::uno::Reference< css::reflection::XTypeDescription >(
+ new SimpleTypeDescription(rTypeClass, name)));
+ }
+ }
+ if (name.startsWith("[]")) {
+ return getSequenceType(name);
+ }
+ sal_Int32 i = name.indexOf('<');
+ if (i != -1) {
+ return getInstantiatedStruct(name, i);
+ }
+ i = name.indexOf("::");
+ if (i != -1) {
+ return getInterfaceMember(name, i);
+ }
+ rtl::Reference< unoidl::Entity > ent(findEntity(name));
+ if (ent.is()) {
+ return getNamed(name, ent);
+ }
+ i = name.lastIndexOf('.');
+ if (i != -1) {
+ OUString parent(name.copy(0, i));
+ ent = findEntity(parent);
+ if (ent.is()) {
+ switch (ent->getSort()) {
+ case unoidl::Entity::SORT_ENUM_TYPE:
+ return getEnumMember(
+ static_cast< unoidl::EnumTypeEntity * >(ent.get()),
+ name.subView(i + 1));
+ case unoidl::Entity::SORT_CONSTANT_GROUP:
+ return getConstant(
+ parent,
+ static_cast< unoidl::ConstantGroupEntity * >(ent.get()),
+ name.subView(i + 1));
+ default:
+ break;
+ }
+ }
+ }
+ return css::uno::Any();
+}
+
+css::uno::Reference< css::reflection::XTypeDescription >
+cppuhelper::TypeManager::resolve(OUString const & name) {
+ css::uno::Reference< css::reflection::XTypeDescription > desc(
+ find(name), css::uno::UNO_QUERY);
+ if (!desc.is()) {
+ throw css::uno::DeploymentException(
+ "cannot resolve type \"" + name + "\"",
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ return desc;
+}
+
+cppuhelper::TypeManager::~TypeManager() noexcept {}
+
+void cppuhelper::TypeManager::disposing() {} //TODO
+
+OUString cppuhelper::TypeManager::getImplementationName()
+{
+ return
+ "com.sun.star.comp.cppuhelper.bootstrap.TypeManager";
+}
+
+sal_Bool cppuhelper::TypeManager::supportsService(
+ OUString const & ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+css::uno::Sequence< OUString >
+cppuhelper::TypeManager::getSupportedServiceNames()
+{
+ return { "com.sun.star.reflection.TypeDescriptionManager" }; //TODO
+}
+
+css::uno::Any cppuhelper::TypeManager::getByHierarchicalName(
+ OUString const & aName)
+{
+ css::uno::Any desc(find(aName));
+ if (!desc.hasValue()) {
+ throw css::container::NoSuchElementException(
+ aName, static_cast< cppu::OWeakObject * >(this));
+ }
+ return desc;
+}
+
+sal_Bool cppuhelper::TypeManager::hasByHierarchicalName(
+ OUString const & aName)
+{
+ return find(aName).hasValue();
+}
+
+css::uno::Type cppuhelper::TypeManager::getElementType()
+{
+ return cppu::UnoType< OUString >::get();
+}
+
+sal_Bool cppuhelper::TypeManager::hasElements()
+{
+ throw css::uno::RuntimeException(
+ "TypeManager hasElements: method not supported",
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+css::uno::Reference< css::container::XEnumeration >
+cppuhelper::TypeManager::createEnumeration()
+{
+ throw css::uno::RuntimeException(
+ "TypeManager createEnumeration: method not supported",
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+sal_Bool cppuhelper::TypeManager::has(css::uno::Any const &)
+{
+ throw css::uno::RuntimeException(
+ "TypeManager has: method not supported",
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+void cppuhelper::TypeManager::insert(css::uno::Any const & aElement)
+{
+ OUString uri;
+ if (!(aElement >>= uri)) {
+ throw css::lang::IllegalArgumentException(
+ ("css.uno.theTypeDescriptionManager.insert expects a string URI"
+ " argument"),
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ //TODO: check for ElementExistException
+ //TODO: check for consistency with existing data
+ readRdbFile(uri, false);
+}
+
+void cppuhelper::TypeManager::remove(css::uno::Any const & aElement)
+{
+ OUString uri;
+ if (!(aElement >>= uri)) {
+ throw css::lang::IllegalArgumentException(
+ ("css.uno.theTypeDescriptionManager.remove expects a string URI"
+ " argument"),
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ //TODO: remove requests are silently ignored for now
+}
+
+css::uno::Reference< css::reflection::XTypeDescriptionEnumeration >
+cppuhelper::TypeManager::createTypeDescriptionEnumeration(
+ OUString const & moduleName,
+ css::uno::Sequence< css::uno::TypeClass > const & types,
+ css::reflection::TypeDescriptionSearchDepth depth)
+{
+ rtl::Reference< unoidl::MapCursor > cursor;
+ try {
+ cursor = manager_->createCursor(moduleName);
+ } catch (unoidl::FileFormatException & e) {
+ throw css::uno::DeploymentException(
+ ("unoidl::FileFormatException for <" + e.getUri() + ">: "
+ + e.getDetail()),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ if (!cursor.is()) {
+ //TODO: css::reflection::InvalidTypeNameException if moduleName names a
+ // non-module
+ throw css::reflection::NoSuchTypeNameException(
+ moduleName, static_cast< cppu::OWeakObject * >(this));
+ }
+ return new Enumeration(
+ this, makePrefix(moduleName), cursor, types,
+ depth == css::reflection::TypeDescriptionSearchDepth_INFINITE);
+}
+
+void cppuhelper::TypeManager::init(std::u16string_view rdbUris) {
+ for (sal_Int32 i = 0; i != -1;) {
+ std::u16string_view uri(o3tl::getToken(rdbUris, 0, ' ', i));
+ if (uri.empty()) {
+ continue;
+ }
+ bool optional;
+ bool directory;
+ cppu::decodeRdbUri(&uri, &optional, &directory);
+ if (directory) {
+ readRdbDirectory(uri, optional);
+ } else {
+ readRdbFile(uri, optional);
+ }
+ }
+}
+
+void cppuhelper::TypeManager::readRdbDirectory(
+ std::u16string_view uri, bool optional)
+{
+ osl::Directory dir = OUString(uri);
+ switch (dir.open()) {
+ case osl::FileBase::E_None:
+ break;
+ case osl::FileBase::E_NOENT:
+ if (optional) {
+ SAL_INFO("cppuhelper", "Ignored optional " << OUString(uri));
+ return;
+ }
+ [[fallthrough]];
+ default:
+ throw css::uno::DeploymentException(
+ OUString::Concat("Cannot open directory ") + uri,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ for (;;) {
+ OUString url;
+ if (!cppu::nextDirectoryItem(dir, &url)) {
+ break;
+ }
+ readRdbFile(url, false);
+ }
+}
+
+void cppuhelper::TypeManager::readRdbFile(
+ std::u16string_view uri, bool optional)
+{
+ try {
+ manager_->addProvider(OUString(uri));
+ } catch (unoidl::NoSuchFileException &) {
+ if (!optional) {
+ throw css::uno::DeploymentException(
+ OUString::Concat(uri) + ": no such file",
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ SAL_INFO("cppuhelper", "Ignored optional " << OUString(uri));
+ } catch (unoidl::FileFormatException & e) {
+ throw css::uno::DeploymentException(
+ ("unoidl::FileFormatException for <" + e.getUri() + ">: "
+ + e.getDetail()),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+}
+
+css::uno::Any cppuhelper::TypeManager::getSequenceType(
+ OUString const & name)
+{
+ assert(name.startsWith("[]"));
+ return css::uno::Any(
+ css::uno::Reference< css::reflection::XTypeDescription >(
+ new SequenceTypeDescription(
+ this, name, name.copy(std::strlen("[]")))));
+}
+
+css::uno::Any cppuhelper::TypeManager::getInstantiatedStruct(
+ OUString const & name, sal_Int32 separator)
+{
+ assert(name.indexOf('<') == separator && separator != -1);
+ rtl::Reference< unoidl::Entity > ent(findEntity(name.copy(0, separator)));
+ if (!ent.is()
+ || (ent->getSort()
+ != unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE))
+ {
+ return css::uno::Any();
+ }
+ rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > ent2(
+ static_cast< unoidl::PolymorphicStructTypeTemplateEntity * >(
+ ent.get()));
+ std::vector< OUString > args;
+ sal_Int32 i = separator;
+ do {
+ ++i; // skip '<' or ','
+ sal_Int32 j = i;
+ for (sal_Int32 level = 0; j != name.getLength(); ++j) {
+ sal_Unicode c = name[j];
+ if (c == ',') {
+ if (level == 0) {
+ break;
+ }
+ } else if (c == '<') {
+ ++level;
+ } else if (c == '>') {
+ if (level == 0) {
+ break;
+ }
+ --level;
+ }
+ }
+ if (j != name.getLength()) {
+ args.push_back(name.copy(i, j - i));
+ }
+ i = j;
+ } while (i != name.getLength() && name[i] != '>');
+ if (i != name.getLength() - 1 || name[i] != '>'
+ || args.size() != ent2->getTypeParameters().size())
+ {
+ return css::uno::Any();
+ }
+ return css::uno::Any(
+ css::uno::Reference< css::reflection::XTypeDescription >(
+ new InstantiatedPolymorphicStructTypeDescription(
+ this, name, ent2, std::move(args))));
+}
+
+css::uno::Any cppuhelper::TypeManager::getInterfaceMember(
+ std::u16string_view name, std::size_t separator)
+{
+ assert(name.find(u"::") == separator && separator != std::u16string_view::npos);
+ css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > ifc(
+ resolveTypedefs(find(OUString(name.substr(0, separator)))), css::uno::UNO_QUERY);
+ if (!ifc.is()) {
+ return css::uno::Any();
+ }
+ std::u16string_view member = name.substr(separator + std::strlen("::"));
+ const css::uno::Sequence<
+ css::uno::Reference<
+ css::reflection::XInterfaceMemberTypeDescription > > mems(
+ ifc->getMembers());
+ for (const auto & m : mems) {
+ if (m->getMemberName() == member) {
+ return css::uno::Any(
+ css::uno::Reference< css::reflection::XTypeDescription >(m));
+ }
+ }
+ return css::uno::Any();
+}
+
+css::uno::Any cppuhelper::TypeManager::getNamed(
+ OUString const & name, rtl::Reference< unoidl::Entity > const & entity)
+{
+ assert(entity.is());
+ switch (entity->getSort()) {
+ case unoidl::Entity::SORT_MODULE:
+ return css::uno::Any(
+ css::uno::Reference< css::reflection::XTypeDescription >(
+ new ModuleDescription(
+ this, name,
+ static_cast< unoidl::ModuleEntity * >(entity.get()))));
+ case unoidl::Entity::SORT_ENUM_TYPE:
+ return css::uno::Any(
+ css::uno::Reference< css::reflection::XTypeDescription >(
+ new EnumTypeDescription(
+ name,
+ static_cast< unoidl::EnumTypeEntity * >(entity.get()))));
+ case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
+ return css::uno::Any(
+ css::uno::Reference< css::reflection::XTypeDescription >(
+ new PlainStructTypeDescription(
+ this, name,
+ static_cast< unoidl::PlainStructTypeEntity * >(
+ entity.get()))));
+ case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
+ return css::uno::Any(
+ css::uno::Reference< css::reflection::XTypeDescription >(
+ new PolymorphicStructTypeTemplateDescription(
+ this, name,
+ static_cast<
+ unoidl::PolymorphicStructTypeTemplateEntity * >(
+ entity.get()))));
+ case unoidl::Entity::SORT_EXCEPTION_TYPE:
+ return css::uno::Any(
+ css::uno::Reference< css::reflection::XTypeDescription >(
+ new ExceptionTypeDescription(
+ this, name,
+ static_cast< unoidl::ExceptionTypeEntity * >(
+ entity.get()))));
+ case unoidl::Entity::SORT_INTERFACE_TYPE:
+ return css::uno::Any(
+ css::uno::Reference< css::reflection::XTypeDescription >(
+ new InterfaceTypeDescription(
+ this, name,
+ static_cast< unoidl::InterfaceTypeEntity * >(
+ entity.get()))));
+ case unoidl::Entity::SORT_TYPEDEF:
+ return css::uno::Any(
+ css::uno::Reference< css::reflection::XTypeDescription >(
+ new TypedefDescription(
+ this, name,
+ static_cast< unoidl::TypedefEntity * >(entity.get()))));
+ case unoidl::Entity::SORT_CONSTANT_GROUP:
+ return css::uno::Any(
+ css::uno::Reference< css::reflection::XTypeDescription >(
+ new ConstantGroupDescription(
+ name,
+ static_cast< unoidl::ConstantGroupEntity * >(
+ entity.get()))));
+ case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
+ return css::uno::Any(
+ css::uno::Reference< css::reflection::XTypeDescription >(
+ new SingleInterfaceBasedServiceDescription(
+ this, name,
+ static_cast< unoidl::SingleInterfaceBasedServiceEntity * >(
+ entity.get()))));
+ case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
+ return css::uno::Any(
+ css::uno::Reference< css::reflection::XTypeDescription >(
+ new AccumulationBasedServiceDescription(
+ this, name,
+ static_cast< unoidl::AccumulationBasedServiceEntity * >(
+ entity.get()))));
+ case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
+ return css::uno::Any(
+ css::uno::Reference< css::reflection::XTypeDescription >(
+ new InterfaceBasedSingletonDescription(
+ this, name,
+ static_cast< unoidl::InterfaceBasedSingletonEntity * >(
+ entity.get()))));
+ case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
+ return css::uno::Any(
+ css::uno::Reference< css::reflection::XTypeDescription >(
+ new ServiceBasedSingletonDescription(
+ this, name,
+ static_cast< unoidl::ServiceBasedSingletonEntity * >(
+ entity.get()))));
+ default:
+ for (;;) { std::abort(); } // this cannot happen
+ }
+}
+
+css::uno::Any cppuhelper::TypeManager::getEnumMember(
+ rtl::Reference< unoidl::EnumTypeEntity > const & entity,
+ std::u16string_view member)
+{
+ auto i = std::find_if(entity->getMembers().begin(), entity->getMembers().end(),
+ [&member](const unoidl::EnumTypeEntity::Member& rMember) { return rMember.name == member; });
+ if (i != entity->getMembers().end())
+ return css::uno::Any(i->value);
+ return css::uno::Any();
+}
+
+css::uno::Any cppuhelper::TypeManager::getConstant(
+ std::u16string_view constantGroupName,
+ rtl::Reference< unoidl::ConstantGroupEntity > const & entity,
+ std::u16string_view member)
+{
+ auto i = std::find_if(entity->getMembers().begin(), entity->getMembers().end(),
+ [&member](const unoidl::ConstantGroupEntity::Member& rMember) { return rMember.name == member; });
+ if (i != entity->getMembers().end())
+ return css::uno::Any(
+ css::uno::Reference< css::reflection::XTypeDescription >(
+ new ConstantDescription(OUString(constantGroupName), *i)));
+ return css::uno::Any();
+}
+
+rtl::Reference< unoidl::Entity > cppuhelper::TypeManager::findEntity(
+ OUString const & name)
+{
+ try {
+ return manager_->findEntity(name);
+ } catch (unoidl::FileFormatException & e) {
+ throw css::uno::DeploymentException(
+ ("unoidl::FileFormatException for <" + e.getUri() + ">: "
+ + e.getDetail()),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/typemanager.hxx b/cppuhelper/source/typemanager.hxx
new file mode 100644
index 000000000..24fe0ef12
--- /dev/null
+++ b/cppuhelper/source/typemanager.hxx
@@ -0,0 +1,127 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <cstddef>
+
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/container/XSet.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/reflection/TypeDescriptionSearchDepth.hpp>
+#include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <rtl/ref.hxx>
+#include <sal/types.h>
+
+namespace com::sun::star {
+ namespace reflection { class XTypeDescription; }
+}
+namespace unoidl {
+ class ConstantGroupEntity;
+ class Entity;
+ class EnumTypeEntity;
+ class Manager;
+}
+
+namespace cppuhelper {
+
+typedef cppu::WeakComponentImplHelper<
+ css::lang::XServiceInfo, css::container::XHierarchicalNameAccess,
+ css::container::XSet, css::reflection::XTypeDescriptionEnumerationAccess >
+TypeManager_Base;
+
+class TypeManager: private cppu::BaseMutex, public TypeManager_Base {
+public:
+ TypeManager();
+
+ using TypeManager_Base::acquire;
+ using TypeManager_Base::release;
+
+ void init(std::u16string_view rdbUris);
+
+ css::uno::Any find(OUString const & name);
+
+ css::uno::Reference< css::reflection::XTypeDescription > resolve(
+ OUString const & name);
+
+private:
+ virtual ~TypeManager() noexcept override;
+
+ virtual void SAL_CALL disposing() override;
+
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedServiceNames() override;
+
+ virtual css::uno::Any SAL_CALL getByHierarchicalName(
+ OUString const & aName) override;
+
+ virtual sal_Bool SAL_CALL hasByHierarchicalName(OUString const & aName) override;
+
+ virtual css::uno::Type SAL_CALL getElementType() override;
+
+ virtual sal_Bool SAL_CALL hasElements() override;
+
+ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL
+ createEnumeration() override;
+
+ virtual sal_Bool SAL_CALL has(css::uno::Any const & aElement) override;
+
+ virtual void SAL_CALL insert(css::uno::Any const & aElement) override;
+
+ virtual void SAL_CALL remove(css::uno::Any const & aElement) override;
+
+ virtual css::uno::Reference< css::reflection::XTypeDescriptionEnumeration >
+ SAL_CALL createTypeDescriptionEnumeration(
+ OUString const & moduleName,
+ css::uno::Sequence< css::uno::TypeClass > const & types,
+ css::reflection::TypeDescriptionSearchDepth depth) override;
+
+ void readRdbDirectory(std::u16string_view uri, bool optional);
+
+ void readRdbFile(std::u16string_view uri, bool optional);
+
+ css::uno::Any getSequenceType(OUString const & name);
+
+ css::uno::Any getInstantiatedStruct(
+ OUString const & name, sal_Int32 separator);
+
+ css::uno::Any getInterfaceMember(
+ std::u16string_view name, std::size_t separator);
+
+ css::uno::Any getNamed(
+ OUString const & name,
+ rtl::Reference< unoidl::Entity > const & entity);
+
+ static css::uno::Any getEnumMember(
+ rtl::Reference< unoidl::EnumTypeEntity > const & entity,
+ std::u16string_view member);
+
+ static css::uno::Any getConstant(
+ std::u16string_view constantGroupName,
+ rtl::Reference< unoidl::ConstantGroupEntity > const & entity,
+ std::u16string_view member);
+
+ rtl::Reference< unoidl::Entity > findEntity(OUString const & name);
+
+ rtl::Reference< unoidl::Manager > manager_;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/typeprovider.cxx b/cppuhelper/source/typeprovider.cxx
new file mode 100644
index 000000000..649e0ed55
--- /dev/null
+++ b/cppuhelper/source/typeprovider.cxx
@@ -0,0 +1,238 @@
+/* -*- 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 <cppuhelper/typeprovider.hxx>
+
+#include <rtl/uuid.h>
+#include <osl/mutex.hxx>
+
+#include <algorithm>
+
+using namespace osl;
+using namespace com::sun::star::uno;
+
+namespace cppu
+{
+
+// suppress spurious warning triggered by SAL_DEPRECATED in class declaration
+#if defined _MSC_VER && !defined __clang__
+#pragma warning(push)
+#pragma warning(disable: 4996)
+#endif
+
+OImplementationId::~OImplementationId()
+{
+ delete _pSeq;
+}
+
+#if defined _MSC_VER && !defined __clang__
+#pragma warning(pop)
+#endif
+
+Sequence< sal_Int8 > OImplementationId::getImplementationId() const
+{
+ if (! _pSeq)
+ {
+ MutexGuard aGuard( Mutex::getGlobalMutex() );
+ if (! _pSeq)
+ {
+ Sequence< sal_Int8 > * pSeq = new Sequence< sal_Int8 >( 16 );
+ ::rtl_createUuid( reinterpret_cast<sal_uInt8 *>(pSeq->getArray()), nullptr, _bUseEthernetAddress );
+ _pSeq = pSeq;
+ }
+ }
+ return *_pSeq;
+}
+
+namespace
+{
+sal_Int32 TypeSeqLen(const Sequence<Type>& s) { return s.getLength(); }
+template <class... Args> sal_Int32 TypeSeqLen(const Type&, Args... args)
+{
+ return 1 + TypeSeqLen(args...);
+}
+
+void PutToTypeSeq(Type* p, const Sequence<Type>& s) { std::copy(s.begin(), s.end(), p); }
+template <class... Args> void PutToTypeSeq(Type* p, const Type& t, Args... args)
+{
+ *p = t;
+ PutToTypeSeq(p + 1, args...);
+}
+
+template <class... Args> Sequence<Type> InitTypeSeq(Args... args)
+{
+ Sequence<Type> s(TypeSeqLen(args...));
+ PutToTypeSeq(s.getArray(), args...);
+ return s;
+}
+}
+
+OTypeCollection::OTypeCollection(
+ const Type & rT1,
+ const Sequence< Type > & rMore )
+ : _aTypes(InitTypeSeq(rT1, rMore))
+{
+}
+
+OTypeCollection::OTypeCollection(
+ const Type & rT1,
+ const Type & rT2,
+ const Sequence< Type > & rMore )
+ : _aTypes(InitTypeSeq(rT1, rT2, rMore))
+{
+}
+
+OTypeCollection::OTypeCollection(
+ const Type & rT1,
+ const Type & rT2,
+ const Type & rT3,
+ const Sequence< Type > & rMore )
+ : _aTypes(InitTypeSeq(rT1, rT2, rT3, rMore))
+{
+}
+
+OTypeCollection::OTypeCollection(
+ const Type & rT1,
+ const Type & rT2,
+ const Type & rT3,
+ const Type & rT4,
+ const Sequence< Type > & rMore )
+ : _aTypes(InitTypeSeq(rT1, rT2, rT3, rT4, rMore))
+{
+}
+
+OTypeCollection::OTypeCollection(
+ const Type & rT1,
+ const Type & rT2,
+ const Type & rT3,
+ const Type & rT4,
+ const Type & rT5,
+ const Sequence< Type > & rMore )
+ : _aTypes(InitTypeSeq(rT1, rT2, rT3, rT4, rT5, rMore))
+{
+}
+
+OTypeCollection::OTypeCollection(
+ const Type & rT1,
+ const Type & rT2,
+ const Type & rT3,
+ const Type & rT4,
+ const Type & rT5,
+ const Type & rT6,
+ const Sequence< Type > & rMore )
+ : _aTypes(InitTypeSeq(rT1, rT2, rT3, rT4, rT5, rT6, rMore))
+{
+}
+
+OTypeCollection::OTypeCollection(
+ const Type & rT1,
+ const Type & rT2,
+ const Type & rT3,
+ const Type & rT4,
+ const Type & rT5,
+ const Type & rT6,
+ const Type & rT7,
+ const Sequence< Type > & rMore )
+ : _aTypes(InitTypeSeq(rT1, rT2, rT3, rT4, rT5, rT6, rT7, rMore))
+{
+}
+
+OTypeCollection::OTypeCollection(
+ const Type & rT1,
+ const Type & rT2,
+ const Type & rT3,
+ const Type & rT4,
+ const Type & rT5,
+ const Type & rT6,
+ const Type & rT7,
+ const Type & rT8,
+ const Sequence< Type > & rMore )
+ : _aTypes(InitTypeSeq(rT1, rT2, rT3, rT4, rT5, rT6, rT7, rT8, rMore))
+{
+}
+
+OTypeCollection::OTypeCollection(
+ const Type & rT1,
+ const Type & rT2,
+ const Type & rT3,
+ const Type & rT4,
+ const Type & rT5,
+ const Type & rT6,
+ const Type & rT7,
+ const Type & rT8,
+ const Type & rT9,
+ const Sequence< Type > & rMore )
+ : _aTypes(InitTypeSeq(rT1, rT2, rT3, rT4, rT5, rT6, rT7, rT8, rT9, rMore))
+{
+}
+
+OTypeCollection::OTypeCollection(
+ const Type & rT1,
+ const Type & rT2,
+ const Type & rT3,
+ const Type & rT4,
+ const Type & rT5,
+ const Type & rT6,
+ const Type & rT7,
+ const Type & rT8,
+ const Type & rT9,
+ const Type & rT10,
+ const Sequence< Type > & rMore )
+ : _aTypes(InitTypeSeq(rT1, rT2, rT3, rT4, rT5, rT6, rT7, rT8, rT9, rT10, rMore))
+{
+}
+
+OTypeCollection::OTypeCollection(
+ const Type & rT1,
+ const Type & rT2,
+ const Type & rT3,
+ const Type & rT4,
+ const Type & rT5,
+ const Type & rT6,
+ const Type & rT7,
+ const Type & rT8,
+ const Type & rT9,
+ const Type & rT10,
+ const Type & rT11,
+ const Sequence< Type > & rMore )
+ : _aTypes(InitTypeSeq(rT1, rT2, rT3, rT4, rT5, rT6, rT7, rT8, rT9, rT10, rT11, rMore))
+{
+}
+
+OTypeCollection::OTypeCollection(
+ const Type & rT1,
+ const Type & rT2,
+ const Type & rT3,
+ const Type & rT4,
+ const Type & rT5,
+ const Type & rT6,
+ const Type & rT7,
+ const Type & rT8,
+ const Type & rT9,
+ const Type & rT10,
+ const Type & rT11,
+ const Type & rT12,
+ const Sequence< Type > & rMore )
+ : _aTypes(InitTypeSeq(rT1, rT2, rT3, rT4, rT5, rT6, rT7, rT8, rT9, rT10, rT11, rT12, rMore))
+{
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/unourl.cxx b/cppuhelper/source/unourl.cxx
new file mode 100644
index 000000000..9656dd078
--- /dev/null
+++ b/cppuhelper/source/unourl.cxx
@@ -0,0 +1,267 @@
+/* -*- 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 <cppuhelper/unourl.hxx>
+
+#include <rtl/malformeduriexception.hxx>
+#include <rtl/string.h>
+#include <rtl/textenc.h>
+#include <rtl/uri.h>
+#include <rtl/uri.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/character.hxx>
+#include <sal/types.h>
+
+#include <map>
+#include <memory>
+#include <utility>
+
+using cppu::UnoUrl;
+using cppu::UnoUrlDescriptor;
+
+class UnoUrlDescriptor::Impl
+{
+public:
+ typedef std::map< OUString, OUString > Parameters;
+
+ OUString m_aDescriptor;
+ OUString m_aName;
+ Parameters m_aParameters;
+
+ /** @exception rtl::MalformedUriException
+ */
+ explicit inline Impl(OUString const & m_aDescriptor);
+
+ Impl * clone() const { return new Impl(*this); }
+};
+
+inline UnoUrlDescriptor::Impl::Impl(OUString const & rDescriptor)
+{
+ m_aDescriptor = rDescriptor;
+ enum State { STATE_NAME0, STATE_NAME, STATE_KEY0, STATE_KEY, STATE_VALUE };
+ State eState = STATE_NAME0;
+ sal_Int32 nStart = 0;
+ OUString aKey;
+ for (sal_Int32 i = 0;; ++i)
+ {
+ bool bEnd = i == rDescriptor.getLength();
+ sal_Unicode c = bEnd ? 0 : rDescriptor[i];
+ switch (eState)
+ {
+ case STATE_NAME0:
+ if (bEnd || !rtl::isAsciiAlphanumeric(c))
+ throw rtl::MalformedUriException(
+ "UNO URL contains bad descriptor name");
+ nStart = i;
+ eState = STATE_NAME;
+ break;
+
+ case STATE_NAME:
+ if (bEnd || c == 0x2C) // ','
+ {
+ m_aName
+ = rDescriptor.copy(nStart, i - nStart).toAsciiLowerCase();
+ eState = STATE_KEY0;
+ }
+ else if (!rtl::isAsciiAlphanumeric(c))
+ throw rtl::MalformedUriException(
+ "UNO URL contains bad descriptor name");
+ break;
+
+ case STATE_KEY0:
+ if (bEnd || !rtl::isAsciiAlphanumeric(c))
+ throw rtl::MalformedUriException(
+ "UNO URL contains bad parameter key");
+ nStart = i;
+ eState = STATE_KEY;
+ break;
+
+ case STATE_KEY:
+ if (c == 0x3D) // '='
+ {
+ aKey = rDescriptor.copy(nStart, i - nStart).toAsciiLowerCase();
+ nStart = i + 1;
+ eState = STATE_VALUE;
+ }
+ else if (bEnd || !rtl::isAsciiAlphanumeric(c))
+ throw rtl::MalformedUriException(
+ "UNO URL contains bad parameter key");
+ break;
+
+ case STATE_VALUE:
+ if (bEnd || c == 0x2C) // ','
+ {
+ if (!m_aParameters.emplace(
+ aKey,
+ rtl::Uri::decode(rDescriptor.copy(nStart,
+ i - nStart),
+ rtl_UriDecodeWithCharset,
+ RTL_TEXTENCODING_UTF8)).second)
+ throw rtl::MalformedUriException(
+ "UNO URL contains duplicated parameter");
+ eState = STATE_KEY0;
+ }
+ break;
+ }
+ if (bEnd)
+ break;
+ }
+}
+
+UnoUrlDescriptor::UnoUrlDescriptor(OUString const & rDescriptor):
+ m_pImpl(new Impl(rDescriptor))
+{}
+
+UnoUrlDescriptor::UnoUrlDescriptor(UnoUrlDescriptor const & rOther):
+ m_pImpl(rOther.m_pImpl->clone())
+{}
+
+UnoUrlDescriptor::~UnoUrlDescriptor()
+{
+ delete m_pImpl;
+}
+
+UnoUrlDescriptor & UnoUrlDescriptor::operator =(UnoUrlDescriptor const & rOther)
+{
+ if (this != &rOther)
+ {
+ std::unique_ptr<Impl> newImpl(rOther.m_pImpl->clone());
+ delete m_pImpl;
+ m_pImpl = newImpl.release();
+ }
+ return *this;
+}
+
+OUString const & UnoUrlDescriptor::getDescriptor() const
+{
+ return m_pImpl->m_aDescriptor;
+}
+
+OUString const & UnoUrlDescriptor::getName() const
+{
+ return m_pImpl->m_aName;
+}
+
+bool UnoUrlDescriptor::hasParameter(OUString const & rKey) const
+{
+ return m_pImpl->m_aParameters.find(rKey.toAsciiLowerCase())
+ != m_pImpl->m_aParameters.end();
+}
+
+OUString UnoUrlDescriptor::getParameter(OUString const & rKey) const
+{
+ Impl::Parameters::const_iterator
+ aIt(m_pImpl->m_aParameters.find(rKey.toAsciiLowerCase()));
+ return aIt == m_pImpl->m_aParameters.end() ? OUString() : aIt->second;
+}
+
+class UnoUrl::Impl
+{
+public:
+ UnoUrlDescriptor m_aConnection;
+ UnoUrlDescriptor m_aProtocol;
+ OUString m_aObjectName;
+
+ Impl * clone() const { return new Impl(*this); }
+
+ /** @exception rtl::MalformedUriException
+ */
+ static inline Impl * create(OUString const & rUrl);
+
+private:
+ Impl(OUString const & rConnectionDescriptor,
+ OUString const & rProtocolDescriptor,
+ OUString aObjectName):
+ m_aConnection(rConnectionDescriptor),
+ m_aProtocol(rProtocolDescriptor),
+ m_aObjectName(std::move(aObjectName))
+ {}
+};
+
+inline UnoUrl::Impl * UnoUrl::Impl::create(OUString const & rUrl)
+{
+ if (!rUrl.startsWithIgnoreAsciiCase("uno:"))
+ throw rtl::MalformedUriException("UNO URL does not start with \"uno:\"");
+ sal_Int32 i = RTL_CONSTASCII_LENGTH("uno:");
+ sal_Int32 j = rUrl.indexOf(';', i);
+ if (j < 0)
+ throw rtl::MalformedUriException("UNO URL has too few semicolons");
+ OUString aConnection(rUrl.copy(i, j - i));
+ i = j + 1;
+ j = rUrl.indexOf(0x3B, i); // ';'
+ if (j < 0)
+ throw rtl::MalformedUriException("UNO URL has too few semicolons");
+ OUString aProtocol(rUrl.copy(i, j - i));
+ i = j + 1;
+ if (i == rUrl.getLength())
+ throw rtl::MalformedUriException("UNO URL contains empty ObjectName");
+ for (j = i; j < rUrl.getLength(); ++j)
+ {
+ sal_Unicode c = rUrl[j];
+ if (!rtl::isAsciiAlphanumeric(c) && c != 0x21 && c != 0x24 // '!', '$'
+ && c != 0x26 && c != 0x27 && c != 0x28 // '&', ''', '('
+ && c != 0x29 && c != 0x2A && c != 0x2B // ')', '*', '+'
+ && c != 0x2C && c != 0x2D && c != 0x2E // ',', '-', '.'
+ && c != 0x2F && c != 0x3A && c != 0x3D // '/', ':', '='
+ && c != 0x3F && c != 0x40 && c != 0x5F // '?', '@', '_'
+ && c != 0x7E) // '~'
+ throw rtl::MalformedUriException("UNO URL contains invalid ObjectName");
+ }
+ return new Impl(aConnection, aProtocol, rUrl.copy(i));
+}
+
+UnoUrl::UnoUrl(OUString const & rUrl): m_pImpl(Impl::create(rUrl))
+{}
+
+UnoUrl::UnoUrl(UnoUrl const & rOther): m_pImpl(rOther.m_pImpl->clone())
+{}
+
+UnoUrl::~UnoUrl()
+{
+ delete m_pImpl;
+}
+
+UnoUrl & UnoUrl::operator =(UnoUrl const & rOther)
+{
+ if (this != &rOther)
+ {
+ std::unique_ptr<Impl> newImpl(rOther.m_pImpl->clone());
+ delete m_pImpl;
+ m_pImpl = newImpl.release();
+ }
+ return *this;
+}
+
+UnoUrlDescriptor const & UnoUrl::getConnection() const
+{
+ return m_pImpl->m_aConnection;
+}
+
+UnoUrlDescriptor const & UnoUrl::getProtocol() const
+{
+ return m_pImpl->m_aProtocol;
+}
+
+OUString const & UnoUrl::getObjectName() const
+{
+ return m_pImpl->m_aObjectName;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/weak.cxx b/cppuhelper/source/weak.cxx
new file mode 100644
index 000000000..e51f9ccf8
--- /dev/null
+++ b/cppuhelper/source/weak.cxx
@@ -0,0 +1,561 @@
+/* -*- 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 <sal/log.hxx>
+
+#include <osl/diagnose.h>
+#include <cppuhelper/weakagg.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/queryinterface.hxx>
+
+#include <com/sun/star/lang/DisposedException.hpp>
+
+#include <algorithm>
+#include <vector>
+#include <mutex>
+
+using namespace osl;
+using namespace com::sun::star::uno;
+
+namespace cppu
+{
+
+// due to static Reflection destruction from usr, there must be a mutex leak (#73272#)
+// this is used to lock all instances of OWeakConnectionPoint and OWeakRefListener as well as OWeakObject::m_pWeakConnectionPoint
+static std::mutex * gpWeakMutex = new std::mutex;
+
+
+//-- OWeakConnectionPoint ----------------------------------------------------
+
+class OWeakConnectionPoint: public XAdapter
+{
+public:
+ /**
+ Hold the weak object without an acquire (only the pointer).
+ */
+ explicit OWeakConnectionPoint( OWeakObject* pObj )
+ : m_aRefCount( 0 )
+ , m_pObject(pObj)
+ {}
+
+ // noncopyable
+ OWeakConnectionPoint(const OWeakConnectionPoint&) = delete;
+ const OWeakConnectionPoint& operator=(const OWeakConnectionPoint&) = delete;
+
+ // XInterface
+ Any SAL_CALL queryInterface( const Type & rType ) override;
+ void SAL_CALL acquire() noexcept override;
+ void SAL_CALL release() noexcept override;
+
+ // XAdapter
+ css::uno::Reference< css::uno::XInterface > SAL_CALL queryAdapted() override;
+ void SAL_CALL addReference( const css::uno::Reference< css::uno::XReference >& xRef ) override;
+ void SAL_CALL removeReference( const css::uno::Reference< css::uno::XReference >& xRef ) override;
+
+ /// Called from the weak object if the reference count goes to zero.
+ ///
+ /// @throws css::uno::RuntimeException
+ void dispose();
+
+private:
+ virtual ~OWeakConnectionPoint() {}
+
+ /// The reference counter.
+ oslInterlockedCount m_aRefCount;
+ /// The weak object
+ OWeakObject* m_pObject;
+ /// The container to hold the weak references
+ std::vector<Reference<XReference>> m_aReferences;
+};
+
+// XInterface
+Any SAL_CALL OWeakConnectionPoint::queryInterface( const Type & rType )
+{
+ return ::cppu::queryInterface(
+ rType, static_cast< XAdapter * >( this ), static_cast< XInterface * >( this ) );
+}
+
+// XInterface
+void SAL_CALL OWeakConnectionPoint::acquire() noexcept
+{
+#ifdef DBG_UTIL
+ // catch things early which have been deleted and then re-acquired
+ assert(m_aRefCount != -1);
+#endif
+ osl_atomic_increment( &m_aRefCount );
+}
+
+// XInterface
+void SAL_CALL OWeakConnectionPoint::release() noexcept
+{
+ if (! osl_atomic_decrement( &m_aRefCount ))
+ {
+#ifdef DBG_UTIL
+ m_aRefCount = -1;
+#endif
+ delete this;
+ }
+}
+
+void OWeakConnectionPoint::dispose()
+{
+ std::vector<Reference<XReference>> aCopy;
+ { // only hold the mutex while we access the field
+ std::scoped_lock aGuard(*cppu::gpWeakMutex);
+ // OWeakObject is not the only owner of this, so clear m_pObject
+ // so that queryAdapted() won't use it now that it's dead
+ m_pObject = nullptr;
+ // other code is going to call removeReference while we are doing this, so we need a
+ // copy, but since we are disposing and going away, we can just take the original data
+ aCopy.swap(m_aReferences);
+ }
+ Any ex;
+ for (const Reference<XReference> & i : aCopy )
+ {
+ try
+ {
+ i->dispose();
+ }
+ catch (css::lang::DisposedException &) {}
+ catch (RuntimeException &)
+ {
+ ex = cppu::getCaughtException();
+ }
+ }
+ if (ex.hasValue())
+ {
+ cppu::throwException(ex);
+ }
+}
+
+// XInterface
+Reference< XInterface > SAL_CALL OWeakConnectionPoint::queryAdapted()
+{
+ Reference< XInterface > ret;
+
+ {
+ std::scoped_lock guard(*gpWeakMutex);
+
+ if (!m_pObject)
+ return ret;
+
+ oslInterlockedCount n = osl_atomic_increment( &m_pObject->m_refCount );
+
+ if (n <= 1)
+ {
+ // Another thread wait in the dispose method at the guard
+ osl_atomic_decrement( &m_pObject->m_refCount );
+ return ret;
+ }
+ }
+
+ // n is now > 1
+ // The reference is incremented. The object cannot be destroyed.
+ // Release the guard at the earliest point.
+ // WeakObject has a (XInterface *) cast operator
+ ret = *m_pObject;
+ osl_atomic_decrement( &m_pObject->m_refCount );
+
+ return ret;
+}
+
+// XInterface
+void SAL_CALL OWeakConnectionPoint::addReference(const Reference< XReference >& rRef)
+{
+ std::scoped_lock aGuard(*gpWeakMutex);
+ m_aReferences.push_back( rRef );
+}
+
+// XInterface
+void SAL_CALL OWeakConnectionPoint::removeReference(const Reference< XReference >& rRef)
+{
+ std::scoped_lock aGuard(*gpWeakMutex);
+ // Search from end because the thing that last added a ref is most likely to be the
+ // first to remove a ref.
+ // It's not really valid to compare the pointer directly, but it's faster.
+ auto it = std::find_if(m_aReferences.rbegin(), m_aReferences.rend(),
+ [&rRef](const Reference<XReference>& rxRef) { return rxRef.get() == rRef.get(); });
+ if (it != m_aReferences.rend()) {
+ m_aReferences.erase( it.base()-1 );
+ return;
+ }
+ // interface not found, use the correct compare method
+ it = std::find(m_aReferences.rbegin(), m_aReferences.rend(), rRef);
+ if ( it != m_aReferences.rend() )
+ m_aReferences.erase( it.base()-1 );
+}
+
+
+//-- OWeakObject -------------------------------------------------------
+
+// XInterface
+Any SAL_CALL OWeakObject::queryInterface( const Type & rType )
+{
+ return ::cppu::queryInterface(
+ rType,
+ static_cast< XWeak * >( this ), static_cast< XInterface * >( this ) );
+}
+
+// XInterface
+void SAL_CALL OWeakObject::acquire() noexcept
+{
+ osl_atomic_increment( &m_refCount );
+}
+
+// XInterface
+void SAL_CALL OWeakObject::release() noexcept
+{
+ if (osl_atomic_decrement( &m_refCount ) == 0) {
+ // notify/clear all weak-refs before object's dtor is executed
+ // (which may check weak-refs to this object):
+ disposeWeakConnectionPoint();
+ // destroy object:
+ delete this;
+ }
+}
+
+void OWeakObject::disposeWeakConnectionPoint()
+{
+ OSL_PRECOND( m_refCount == 0, "OWeakObject::disposeWeakConnectionPoint: only to be called with a ref count of 0!" );
+ if (m_pWeakConnectionPoint != nullptr) {
+ OWeakConnectionPoint * const p = m_pWeakConnectionPoint;
+ m_pWeakConnectionPoint = nullptr;
+ try {
+ p->dispose();
+ }
+ catch (RuntimeException const& exc) {
+ SAL_WARN( "cppuhelper", exc );
+ }
+ p->release();
+ }
+}
+
+OWeakObject::~OWeakObject() COVERITY_NOEXCEPT_FALSE
+{
+}
+
+// XWeak
+Reference< XAdapter > SAL_CALL OWeakObject::queryAdapter()
+{
+ if (!m_pWeakConnectionPoint)
+ {
+ // only acquire mutex if member is not created
+ std::scoped_lock aGuard( *gpWeakMutex );
+ if( !m_pWeakConnectionPoint )
+ {
+ OWeakConnectionPoint * p = new OWeakConnectionPoint(this);
+ p->acquire();
+ m_pWeakConnectionPoint = p;
+ }
+ }
+
+ return m_pWeakConnectionPoint;
+}
+
+
+//-- OWeakAggObject ----------------------------------------------------
+
+OWeakAggObject::~OWeakAggObject()
+{
+}
+
+// XInterface
+void OWeakAggObject::acquire() noexcept
+{
+ Reference<XInterface > x( xDelegator );
+ if (x.is())
+ x->acquire();
+ else
+ OWeakObject::acquire();
+}
+
+// XInterface
+void OWeakAggObject::release() noexcept
+{
+ Reference<XInterface > x( xDelegator );
+ if (x.is())
+ x->release();
+ else
+ OWeakObject::release();
+}
+
+// XInterface
+Any OWeakAggObject::queryInterface( const Type & rType )
+{
+ Reference< XInterface > x( xDelegator ); // harden ref
+ return (x.is() ? x->queryInterface( rType ) : queryAggregation( rType ));
+}
+
+// XAggregation
+Any OWeakAggObject::queryAggregation( const Type & rType )
+{
+ return ::cppu::queryInterface(
+ rType,
+ static_cast< XInterface * >( static_cast< OWeakObject * >( this ) ),
+ static_cast< XAggregation * >( this ),
+ static_cast< XWeak * >( this ) );
+}
+
+// XAggregation
+void OWeakAggObject::setDelegator( const Reference<XInterface > & rDelegator )
+{
+ xDelegator = rDelegator;
+}
+
+}
+
+namespace com::sun::star::uno
+{
+
+
+//-- OWeakRefListener -----------------------------------------------------
+
+class OWeakRefListener final : public XReference
+{
+public:
+ explicit OWeakRefListener(const Reference< XInterface >& xInt);
+ explicit OWeakRefListener(const Reference< XWeak >& xInt);
+ virtual ~OWeakRefListener();
+
+ // noncopyable
+ OWeakRefListener(const OWeakRefListener&) = delete;
+ const OWeakRefListener& operator=(const OWeakRefListener&) = delete;
+
+ // XInterface
+ Any SAL_CALL queryInterface( const Type & rType ) override;
+ void SAL_CALL acquire() noexcept override;
+ void SAL_CALL release() noexcept override;
+
+ // XReference
+ void SAL_CALL dispose() override;
+
+ /// The reference counter.
+ oslInterlockedCount m_aRefCount;
+ /// The connection point of the weak object, guarded by getWeakMutex()
+ Reference< XAdapter > m_XWeakConnectionPoint;
+};
+
+OWeakRefListener::OWeakRefListener(const Reference< XInterface >& xInt)
+ : m_aRefCount( 1 )
+{
+ try
+ {
+ Reference< XWeak > xWeak( Reference< XWeak >::query( xInt ) );
+
+ if (xWeak.is())
+ {
+ m_XWeakConnectionPoint = xWeak->queryAdapter();
+
+ if (m_XWeakConnectionPoint.is())
+ {
+ m_XWeakConnectionPoint->addReference(static_cast<XReference*>(this));
+ }
+ }
+ }
+ catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
+ osl_atomic_decrement( &m_aRefCount );
+}
+
+OWeakRefListener::OWeakRefListener(const Reference< XWeak >& xWeak)
+ : m_aRefCount( 1 )
+{
+ m_XWeakConnectionPoint = xWeak->queryAdapter();
+
+ if (m_XWeakConnectionPoint.is())
+ {
+ m_XWeakConnectionPoint->addReference(static_cast<XReference*>(this));
+ }
+ osl_atomic_decrement( &m_aRefCount );
+}
+
+OWeakRefListener::~OWeakRefListener()
+{
+ try
+ {
+ if (m_XWeakConnectionPoint.is())
+ {
+ acquire(); // don't die again
+ m_XWeakConnectionPoint->removeReference(static_cast<XReference*>(this));
+ }
+ }
+ catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
+}
+
+// XInterface
+Any SAL_CALL OWeakRefListener::queryInterface( const Type & rType )
+{
+ return ::cppu::queryInterface(
+ rType, static_cast< XReference * >( this ), static_cast< XInterface * >( this ) );
+}
+
+// XInterface
+void SAL_CALL OWeakRefListener::acquire() noexcept
+{
+ osl_atomic_increment( &m_aRefCount );
+}
+
+// XInterface
+void SAL_CALL OWeakRefListener::release() noexcept
+{
+ if( ! osl_atomic_decrement( &m_aRefCount ) )
+ delete this;
+}
+
+void SAL_CALL OWeakRefListener::dispose()
+{
+ Reference< XAdapter > xAdp;
+ {
+ std::scoped_lock guard(*cppu::gpWeakMutex);
+ if( m_XWeakConnectionPoint.is() )
+ {
+ xAdp = m_XWeakConnectionPoint;
+ m_XWeakConnectionPoint.clear();
+ }
+ }
+
+ if( xAdp.is() )
+ xAdp->removeReference(static_cast<XReference*>(this));
+}
+
+
+//-- WeakReferenceHelper ----------------------------------------------------------
+
+WeakReferenceHelper::WeakReferenceHelper(const Reference< XInterface >& xInt)
+ : m_pImpl( nullptr )
+{
+ if (xInt.is())
+ {
+ m_pImpl = new OWeakRefListener(xInt);
+ m_pImpl->acquire();
+ }
+}
+
+WeakReferenceHelper::WeakReferenceHelper(const Reference< XWeak >& xWeak)
+ : m_pImpl( nullptr )
+{
+ if (xWeak.is())
+ {
+ m_pImpl = new OWeakRefListener(xWeak);
+ m_pImpl->acquire();
+ }
+}
+
+WeakReferenceHelper::WeakReferenceHelper(const WeakReferenceHelper& rWeakRef)
+ : m_pImpl( nullptr )
+{
+ Reference< XInterface > xInt( rWeakRef.get() );
+ if (xInt.is())
+ {
+ m_pImpl = new OWeakRefListener(xInt);
+ m_pImpl->acquire();
+ }
+}
+
+void WeakReferenceHelper::clear()
+{
+ try
+ {
+ if (m_pImpl)
+ {
+ m_pImpl->dispose();
+ m_pImpl->release();
+ m_pImpl = nullptr;
+ }
+ }
+ catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
+}
+
+WeakReferenceHelper& WeakReferenceHelper::operator=(const WeakReferenceHelper& rWeakRef)
+{
+ if (this == &rWeakRef)
+ {
+ return *this;
+ }
+ Reference< XInterface > xInt( rWeakRef.get() );
+ return operator = ( xInt );
+}
+
+WeakReferenceHelper & WeakReferenceHelper::operator =(
+ WeakReferenceHelper && other)
+{
+ clear();
+ std::swap(m_pImpl, other.m_pImpl);
+ return *this;
+}
+
+WeakReferenceHelper & SAL_CALL
+WeakReferenceHelper::operator= (const Reference< XInterface > & xInt)
+{
+ try
+ {
+ clear();
+ if (xInt.is())
+ {
+ m_pImpl = new OWeakRefListener(xInt);
+ m_pImpl->acquire();
+ }
+ }
+ catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
+ return *this;
+}
+
+WeakReferenceHelper &
+WeakReferenceHelper::operator= (const Reference< XWeak > & xWeak)
+{
+ clear();
+ if (xWeak)
+ {
+ m_pImpl = new OWeakRefListener(xWeak);
+ m_pImpl->acquire();
+ }
+ return *this;
+}
+
+WeakReferenceHelper::~WeakReferenceHelper()
+{
+ clear();
+}
+
+Reference< XInterface > WeakReferenceHelper::get() const
+{
+ try
+ {
+ Reference< XAdapter > xAdp;
+ {
+ // must lock to access m_XWeakConnectionPoint
+ std::scoped_lock guard(*cppu::gpWeakMutex);
+ if( m_pImpl && m_pImpl->m_XWeakConnectionPoint.is() )
+ xAdp = m_pImpl->m_XWeakConnectionPoint;
+ }
+
+ if (xAdp.is())
+ return xAdp->queryAdapted();
+ }
+ catch (RuntimeException &)
+ {
+ OSL_ASSERT( false );
+ } // assert here, but no unexpected()
+
+ return Reference< XInterface >();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/unotypes/cppuhelper/detail/XExceptionThrower.idl b/cppuhelper/unotypes/cppuhelper/detail/XExceptionThrower.idl
new file mode 100644
index 000000000..23baea7e5
--- /dev/null
+++ b/cppuhelper/unotypes/cppuhelper/detail/XExceptionThrower.idl
@@ -0,0 +1,41 @@
+/* -*- 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_cppuhelper_detail_XExceptionThrower_idl
+#define INCLUDED_cppuhelper_detail_XExceptionThrower_idl
+
+#include <com/sun/star/uno/Exception.idl>
+#include <com/sun/star/uno/XInterface.idl>
+
+
+module cppuhelper { module detail {
+
+interface XExceptionThrower : com::sun::star::uno::XInterface
+{
+ void throwException( [in] any exc )
+ raises (com::sun::star::uno::Exception);
+ void rethrowException()
+ raises (com::sun::star::uno::Exception);
+};
+
+}; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cpputools/Executable_sp2bv.mk b/cpputools/Executable_sp2bv.mk
new file mode 100644
index 000000000..9ebbfaf3d
--- /dev/null
+++ b/cpputools/Executable_sp2bv.mk
@@ -0,0 +1,26 @@
+# -*- 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_Executable_Executable,sp2bv))
+
+$(eval $(call gb_Executable_use_api,sp2bv,\
+ udkapi \
+))
+
+$(eval $(call gb_Executable_use_libraries,sp2bv,\
+ cppu \
+ cppuhelper \
+ sal \
+))
+
+$(eval $(call gb_Executable_add_exception_objects,sp2bv,\
+ cpputools/source/sp2bv/sp2bv \
+))
+
+# vim:set noet sw=4 ts=4:
diff --git a/cpputools/Executable_uno.mk b/cpputools/Executable_uno.mk
new file mode 100644
index 000000000..ba3b22fb6
--- /dev/null
+++ b/cpputools/Executable_uno.mk
@@ -0,0 +1,33 @@
+# -*- 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_Executable_Executable,uno))
+
+$(eval $(call gb_Executable_use_internal_comprehensive_api,uno,\
+ udkapi \
+))
+
+$(eval $(call gb_Executable_use_libraries,uno,\
+ cppu \
+ cppuhelper \
+ sal \
+ salhelper \
+))
+
+$(eval $(call gb_Executable_use_externals,uno,\
+ libxml2 \
+))
+
+$(eval $(call gb_Executable_add_exception_objects,uno,\
+ cpputools/source/unoexe/unoexe \
+))
+
+$(eval $(call gb_Executable_add_default_nativeres,uno))
+
+# vim:set noet sw=4 ts=4:
diff --git a/cpputools/Makefile b/cpputools/Makefile
new file mode 100644
index 000000000..ccb1c85a0
--- /dev/null
+++ b/cpputools/Makefile
@@ -0,0 +1,7 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+
+module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
+
+include $(module_directory)/../solenv/gbuild/partial_build.mk
+
+# vim: set noet sw=4 ts=4:
diff --git a/cpputools/Module_cpputools.mk b/cpputools/Module_cpputools.mk
new file mode 100644
index 000000000..c71b68e44
--- /dev/null
+++ b/cpputools/Module_cpputools.mk
@@ -0,0 +1,20 @@
+# -*- 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_Module_Module,cpputools))
+
+$(eval $(call gb_Module_add_targets,cpputools,\
+ $(call gb_CondExeSp2bv,Executable_sp2bv) \
+ $(call gb_CondExeUno, \
+ Executable_uno \
+ Package_uno_sh \
+ ) \
+))
+
+# vim:set noet sw=4 ts=4:
diff --git a/cpputools/Package_uno_sh.mk b/cpputools/Package_uno_sh.mk
new file mode 100644
index 000000000..4df4d75f5
--- /dev/null
+++ b/cpputools/Package_uno_sh.mk
@@ -0,0 +1,16 @@
+# -*- 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_Package_Package,uno_sh,$(SRCDIR)/cpputools/scripts))
+
+ifneq (,$(filter-out MACOSX WNT,$(OS)))
+$(eval $(call gb_Package_add_file,uno_sh,$(LIBO_URE_BIN_FOLDER)/uno,uno.sh))
+endif
+
+# vim:set noet sw=4 ts=4:
diff --git a/cpputools/README.md b/cpputools/README.md
new file mode 100644
index 000000000..e6ab397cf
--- /dev/null
+++ b/cpputools/README.md
@@ -0,0 +1,3 @@
+# Old Way of Doing Component Registration
+
+Nowadays replaced by another stand-alone UI and tools called UNO package.
diff --git a/cpputools/scripts/uno.sh b/cpputools/scripts/uno.sh
new file mode 100755
index 000000000..f5222ba1c
--- /dev/null
+++ b/cpputools/scripts/uno.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+#
+# 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 .
+#
+
+# Pass -env arguments on to javaldx; needs to be fixed:
+my_envargs=
+for my_arg in "$@" ; do
+ case ${my_arg} in
+ -env:*) my_envargs="${my_envargs} ${my_arg}" ;;
+ esac
+done
+
+# Extend the LD_LIBRARY_PATH for Java:
+epath=$(dirname "$0")
+if [ -x "${epath}/javaldx" ] ; then
+ jpath=$("${epath}/javaldx" $my_envargs)
+ if [ -n "${jpath}" ]; then
+ sd_platform=$(uname -s)
+ case $sd_platform in
+ AIX)
+ LIBPATH=${jpath}${LIBPATH:+:${LIBPATH}}
+ export LIBPATH
+ ;;
+ *)
+ LD_LIBRARY_PATH=${jpath}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
+ export LD_LIBRARY_PATH
+ ;;
+ esac
+ fi
+fi
+
+exec "$0.bin" "$@"
diff --git a/cpputools/source/sp2bv/readme.txt b/cpputools/source/sp2bv/readme.txt
new file mode 100644
index 000000000..f83b442c8
--- /dev/null
+++ b/cpputools/source/sp2bv/readme.txt
@@ -0,0 +1,8 @@
+This tool converts system paths into file urls and escapes it for use as
+bootstrap variable. For example
+
+c:\program files\App$
+->
+file:///c:/program%20files/App$
+->
+file:///c:/program%20files/App\$
diff --git a/cpputools/source/sp2bv/sp2bv.cxx b/cpputools/source/sp2bv/sp2bv.cxx
new file mode 100644
index 000000000..9998e7cdb
--- /dev/null
+++ b/cpputools/source/sp2bv/sp2bv.cxx
@@ -0,0 +1,122 @@
+/* -*- 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 <stdio.h>
+#include <string.h>
+#include <osl/thread.h>
+#include <osl/file.h>
+#include <rtl/ustrbuf.h>
+
+static bool hasOption(char const * szOption, int argc, char** argv);
+
+
+#define HELP_TEXT \
+"SYNOPSIS \n\n" \
+"\tsp2bv [-h] [-?] string \n\n" \
+"DESCRIPTION\n\n" \
+"\tsp2bv stands for \"system path to bootstrap variable\"." \
+" First the system path is converted into a file URL. Then all " \
+"characters which have a special meaning in bootstrap variables, " \
+"such as \'$\' are escaped. The resulting string is written to " \
+"stdout and can be assigned to a bootstrap variable.\n" \
+"\n\n" \
+"OPTIONS \n\n" \
+"\tThe following options are supported: \n" \
+"-?\n " \
+"--help" \
+" Display help information.\n"
+
+
+int main(int argc, char **argv)
+{
+ if( hasOption("--help",argc, argv) || hasOption("-h", argc, argv))
+ {
+ fprintf(stdout, HELP_TEXT);// default
+ return 0;
+ }
+
+ if (argc != 2)
+ {
+ fprintf(stdout, HELP_TEXT);
+ return -1;
+ }
+
+ rtl_uString* pPath = nullptr;
+ rtl_string2UString( &pPath, argv[1], strlen(argv[1]),
+ osl_getThreadTextEncoding(),OSTRING_TO_OUSTRING_CVTFLAGS );
+
+ rtl_uString* pUrl = nullptr;
+ if (osl_getFileURLFromSystemPath(pPath, &pUrl) != osl_File_E_None)
+ return -1;
+//escape the special characters
+
+ sal_Unicode cEscapeChar = 0x5c;
+ rtl_uString* pBuffer = nullptr;
+ sal_Int32 nCapacity = 255;
+ rtl_uString_new_WithLength( &pBuffer, nCapacity );
+
+ const sal_Unicode* pCur = pUrl->buffer;
+ for (int i = 0; i != pUrl->length; i++)
+ {
+ switch( *pCur)
+ {
+ case '$':
+ rtl_uStringbuffer_insert( &pBuffer, &nCapacity, pBuffer->length, &cEscapeChar, 1);
+ rtl_uStringbuffer_insert( &pBuffer, &nCapacity, pBuffer->length, pCur, 1);
+ break;
+ case '{':
+ case '}':
+ case '\\': fprintf(stderr, "sp2vb: file URL contains invalid characters!\n");
+ return -1;
+ default:
+ rtl_uStringbuffer_insert( &pBuffer, &nCapacity, pBuffer->length, pCur, 1);
+ }
+ pCur ++;
+ }
+//convert back to byte string so that we can print it.
+ rtl_String* pBootVar = nullptr;
+ rtl_uString2String( &pBootVar, pBuffer->buffer, pBuffer->length,
+ osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS);
+
+ fprintf(stdout, "%s", pBootVar->buffer);
+ fflush(stdout);
+
+ rtl_uString_release(pBuffer);
+ rtl_uString_release(pPath);
+ rtl_uString_release(pUrl);
+ rtl_string_release(pBootVar);
+ return 0;
+}
+
+
+static bool hasOption(char const * szOption, int argc, char** argv)
+{
+ bool retVal = false;
+ for(int i= 1; i < argc; i++)
+ {
+ if( ! strcmp(argv[i], szOption))
+ {
+ retVal = true;
+ break;
+ }
+ }
+ return retVal;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cpputools/source/unoexe/unoexe.cxx b/cpputools/source/unoexe/unoexe.cxx
new file mode 100644
index 000000000..f8e5aa12d
--- /dev/null
+++ b/cpputools/source/unoexe/unoexe.cxx
@@ -0,0 +1,543 @@
+/* -*- 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 <stdio.h>
+#include <mutex>
+#include <string_view>
+
+#include <sal/main.h>
+#include <sal/log.hxx>
+#include <o3tl/string_view.hxx>
+#include <osl/diagnose.h>
+#include <osl/mutex.hxx>
+#include <osl/conditn.hxx>
+
+#include <rtl/process.h>
+#include <rtl/ref.hxx>
+
+#include <cppuhelper/bootstrap.hxx>
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/lang/XMain.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XSingleComponentFactory.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/lang/XEventListener.hpp>
+#include <com/sun/star/loader/XImplementationLoader.hpp>
+#include <com/sun/star/registry/XRegistryKey.hpp>
+#include <com/sun/star/connection/Acceptor.hpp>
+#include <com/sun/star/connection/XConnection.hpp>
+#include <com/sun/star/bridge/XBridgeFactory.hpp>
+#include <com/sun/star/bridge/XBridge.hpp>
+
+using namespace osl;
+using namespace cppu;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::loader;
+using namespace com::sun::star::registry;
+using namespace com::sun::star::connection;
+using namespace com::sun::star::bridge;
+using namespace com::sun::star::container;
+
+namespace unoexe
+{
+
+static bool s_quiet = false;
+
+static void out( const char * pText )
+{
+ if (! s_quiet)
+ fputs( pText, stderr );
+}
+
+static void out( std::u16string_view rText )
+{
+ if (! s_quiet)
+ {
+ OString aText( OUStringToOString( rText, RTL_TEXTENCODING_ASCII_US ) );
+ fputs( aText.getStr(), stderr );
+ }
+}
+
+const char arUsingText[] =
+"\nusing:\n\n"
+"uno [-c ComponentImplementationName -l LocationUrl | -s ServiceName]\n"
+" [-u uno:(socket[,host=HostName][,port=nnn]|pipe[,name=PipeName]);<protocol>;Name\n"
+" [--singleaccept] [--singleinstance]]\n"
+" [--quiet]\n"
+" [-- Argument1 Argument2 ...]\n";
+
+/// @throws RuntimeException
+static bool readOption( OUString * pValue, const char * pOpt,
+ sal_uInt32 * pnIndex, const OUString & aArg)
+{
+ static const OUStringLiteral dash(u"-");
+ if(!aArg.startsWith(dash))
+ return false;
+
+ OUString aOpt = OUString::createFromAscii( pOpt );
+
+ if (aArg.getLength() < aOpt.getLength())
+ return false;
+
+ if (aOpt.equalsIgnoreAsciiCase( aArg.subView(1, aArg.getLength()-1) ))
+ {
+ // take next argument
+ ++(*pnIndex);
+
+ rtl_getAppCommandArg(*pnIndex, &pValue->pData);
+ if (*pnIndex >= rtl_getAppCommandArgCount() || pValue->subView(1) == dash)
+ {
+ throw RuntimeException( "incomplete option \"-" + aOpt + "\" given!" );
+ }
+ SAL_INFO("cpputools.unoexe", "> identified option -" << pOpt << " = " << aArg);
+ ++(*pnIndex);
+ return true;
+ }
+ else if (aArg.indexOf(aOpt) == 1)
+ {
+ *pValue = aArg.copy(1 + aOpt.getLength());
+ SAL_INFO("cpputools.unoexe", "> identified option -" << pOpt << " = " << aArg);
+ ++(*pnIndex);
+
+ return true;
+ }
+ return false;
+}
+
+static bool readOption( bool * pbOpt, const char * pOpt,
+ sal_uInt32 * pnIndex, std::u16string_view aArg)
+{
+ OUString aOpt = OUString::createFromAscii(pOpt);
+
+ if(o3tl::starts_with(aArg, u"--") && aOpt == aArg.substr(2))
+ {
+ ++(*pnIndex);
+ *pbOpt = true;
+ SAL_INFO("cpputools.unoexe", "> identified option --" << pOpt);
+ return true;
+ }
+ return false;
+}
+
+/// @throws Exception
+template< class T >
+static void createInstance(
+ Reference< T > & rxOut,
+ const Reference< XComponentContext > & xContext,
+ const OUString & rServiceName )
+{
+ Reference< XMultiComponentFactory > xMgr( xContext->getServiceManager() );
+ Reference< XInterface > x( xMgr->createInstanceWithContext( rServiceName, xContext ) );
+
+ if (! x.is())
+ {
+ throw RuntimeException( "cannot get service instance \"" + rServiceName + "\"!" );
+ }
+
+ rxOut.set( x.get(), UNO_QUERY_THROW );
+}
+
+/// @throws Exception
+static Reference< XInterface > loadComponent(
+ const Reference< XComponentContext > & xContext,
+ const OUString & rImplName, const OUString & rLocation )
+{
+ // determine loader to be used
+ sal_Int32 nDot = rLocation.lastIndexOf( '.' );
+ if (nDot <= 0 || nDot >= rLocation.getLength())
+ {
+ throw RuntimeException(
+ "location \"" + rLocation + "\" has no extension! Cannot determine loader to be used!" );
+ }
+
+ Reference< XImplementationLoader > xLoader;
+
+ std::u16string_view aExt( rLocation.subView( nDot +1 ) );
+
+ if (aExt == u"dll" || aExt == u"exe" || aExt == u"dylib" || aExt == u"so")
+ {
+ createInstance(
+ xLoader, xContext, "com.sun.star.loader.SharedLibrary" );
+ }
+ else if (aExt == u"jar" || aExt == u"class")
+ {
+ createInstance(
+ xLoader, xContext, "com.sun.star.loader.Java" );
+ }
+ else
+ {
+ throw RuntimeException(
+ "unknown extension of \"" + rLocation + "\"! No loader available!" );
+ }
+
+ Reference< XInterface > xInstance;
+
+ // activate
+ Reference< XInterface > xFactory( xLoader->activate(
+ rImplName, OUString(), rLocation, Reference< XRegistryKey >() ) );
+ if (xFactory.is())
+ {
+ Reference< XSingleComponentFactory > xCFac( xFactory, UNO_QUERY );
+ if (xCFac.is())
+ {
+ xInstance = xCFac->createInstanceWithContext( xContext );
+ }
+ else
+ {
+ Reference< XSingleServiceFactory > xSFac( xFactory, UNO_QUERY );
+ if (xSFac.is())
+ {
+ out( "\n> warning: ignoring context for implementation \"" );
+ out( rImplName );
+ out( "\"!" );
+ xInstance = xSFac->createInstance();
+ }
+ }
+ }
+
+ if (! xInstance.is())
+ {
+ throw RuntimeException(
+ "activating component \"" + rImplName + "\" from location \"" + rLocation + "\" failed!" );
+ }
+
+ return xInstance;
+}
+
+namespace {
+
+class OInstanceProvider
+ : public WeakImplHelper< XInstanceProvider >
+{
+ Reference< XComponentContext > _xContext;
+
+ std::mutex _aSingleInstanceMutex;
+ Reference< XInterface > _xSingleInstance;
+ bool _bSingleInstance;
+
+ OUString _aImplName;
+ OUString _aLocation;
+ OUString _aServiceName;
+ Sequence< Any > _aInitParams;
+
+ OUString _aInstanceName;
+
+ /// @throws Exception
+ inline Reference< XInterface > createInstance() const;
+
+public:
+ OInstanceProvider( const Reference< XComponentContext > & xContext,
+ const OUString & rImplName, const OUString & rLocation,
+ const OUString & rServiceName, const Sequence< Any > & rInitParams,
+ bool bSingleInstance, const OUString & rInstanceName )
+ : _xContext( xContext )
+ , _bSingleInstance( bSingleInstance )
+ , _aImplName( rImplName )
+ , _aLocation( rLocation )
+ , _aServiceName( rServiceName )
+ , _aInitParams( rInitParams )
+ , _aInstanceName( rInstanceName )
+ {}
+
+ // XInstanceProvider
+ virtual Reference< XInterface > SAL_CALL getInstance( const OUString & rName ) override;
+};
+
+}
+
+inline Reference< XInterface > OInstanceProvider::createInstance() const
+{
+ Reference< XInterface > xRet;
+ if (!_aImplName.isEmpty()) // manually via loader
+ xRet = loadComponent( _xContext, _aImplName, _aLocation );
+ else // via service manager
+ unoexe::createInstance( xRet, _xContext, _aServiceName );
+
+ // opt XInit
+ Reference< XInitialization > xInit( xRet, UNO_QUERY );
+ if (xInit.is())
+ xInit->initialize( _aInitParams );
+
+ return xRet;
+}
+
+Reference< XInterface > OInstanceProvider::getInstance( const OUString & rName )
+{
+ try
+ {
+ if (_aInstanceName == rName)
+ {
+ Reference< XInterface > xRet;
+
+ if (_aImplName.isEmpty() && _aServiceName.isEmpty())
+ {
+ OSL_ASSERT( rName == "uno.ComponentContext" );
+ xRet = _xContext;
+ }
+ else if (_bSingleInstance)
+ {
+ if (! _xSingleInstance.is())
+ {
+ std::lock_guard aGuard( _aSingleInstanceMutex );
+ if (! _xSingleInstance.is())
+ {
+ _xSingleInstance = createInstance();
+ }
+ }
+ xRet = _xSingleInstance;
+ }
+ else
+ {
+ xRet = createInstance();
+ }
+
+ return xRet;
+ }
+ }
+ catch (Exception & rExc)
+ {
+ out( "\n> error: " );
+ out( rExc.Message );
+ }
+ throw NoSuchElementException(
+ "no such element \"" + rName + "\"!" );
+}
+
+namespace {
+
+struct ODisposingListener : public WeakImplHelper< XEventListener >
+{
+ Condition cDisposed;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const EventObject & rEvt ) override;
+
+ static void waitFor( const Reference< XComponent > & xComp );
+};
+
+}
+
+void ODisposingListener::disposing( const EventObject & )
+{
+ cDisposed.set();
+}
+
+void ODisposingListener::waitFor( const Reference< XComponent > & xComp )
+{
+ rtl::Reference<ODisposingListener> xListener = new ODisposingListener;
+
+ xComp->addEventListener( xListener );
+ xListener->cDisposed.wait();
+}
+
+} // namespace unoexe
+
+using namespace unoexe;
+
+SAL_IMPLEMENT_MAIN()
+{
+ sal_uInt32 nCount = rtl_getAppCommandArgCount();
+ if (nCount == 0)
+ {
+ out( arUsingText );
+ return 0;
+ }
+
+ sal_Int32 nRet = 0;
+ Reference< XComponentContext > xContext;
+
+
+ try
+ {
+ OUString aImplName, aLocation, aServiceName, aUnoUrl;
+ Sequence< OUString > aParams;
+ bool bSingleAccept = false;
+ bool bSingleInstance = false;
+
+ // read command line arguments
+
+ sal_uInt32 nPos = 0;
+ // read up to arguments
+ while (nPos < nCount)
+ {
+ OUString arg;
+
+ rtl_getAppCommandArg(nPos, &arg.pData);
+
+ if (arg == "--")
+ {
+ ++nPos;
+ break;
+ }
+
+ if (!(readOption( &aImplName, "c", &nPos, arg) ||
+ readOption( &aLocation, "l", &nPos, arg) ||
+ readOption( &aServiceName, "s", &nPos, arg) ||
+ readOption( &aUnoUrl, "u", &nPos, arg) ||
+ readOption( &s_quiet, "quiet", &nPos, arg) ||
+ readOption( &bSingleAccept, "singleaccept", &nPos, arg) ||
+ readOption( &bSingleInstance, "singleinstance", &nPos, arg)))
+ {
+ throw RuntimeException(
+ "unexpected argument \"" + arg + "\"" );
+ }
+ }
+
+ if (!(aImplName.isEmpty() || aServiceName.isEmpty()))
+ throw RuntimeException("give component exOR service name!" );
+ if (aImplName.isEmpty() && aServiceName.isEmpty())
+ {
+ if (! aUnoUrl.endsWithIgnoreAsciiCase( ";uno.ComponentContext" ))
+ throw RuntimeException(
+ "expected UNO-URL with instance name uno.ComponentContext!" );
+ if (bSingleInstance)
+ throw RuntimeException(
+ "unexpected option --singleinstance!" );
+ }
+ if (!aImplName.isEmpty() && aLocation.isEmpty())
+ throw RuntimeException("give component location!" );
+ if (!aServiceName.isEmpty() && !aLocation.isEmpty())
+ out( "\n> warning: service name given, will ignore location!" );
+
+ // read component params
+ aParams.realloc( nCount - nPos );
+ OUString * pParams = aParams.getArray();
+
+ sal_uInt32 nOffset = nPos;
+ for ( ; nPos < nCount; ++nPos )
+ {
+ rtl_getAppCommandArg( nPos, &pParams[nPos -nOffset].pData );
+ }
+
+ xContext = defaultBootstrap_InitialComponentContext();
+
+ // accept, instantiate, etc.
+
+ if (!aUnoUrl.isEmpty()) // accepting connections
+ {
+ if (aUnoUrl.getLength() < 10 || !aUnoUrl.startsWithIgnoreAsciiCase( "uno:" ))
+ {
+ throw RuntimeException("illegal uno url given!" );
+ }
+
+ sal_Int32 nIndex = 4; // skip initial "uno:"
+ bool bTooFewTokens {false};
+ const OUString aConnectDescr{ aUnoUrl.getToken( 0, ';', nIndex ) }; // uno:CONNECTDESCR;iiop;InstanceName
+ if (nIndex<0) bTooFewTokens = true;
+ const OUString aUnoUrlToken{ aUnoUrl.getToken( 0, ';', nIndex ) };
+ if (nIndex<0) bTooFewTokens = true;
+ const OUString aInstanceName{ aUnoUrl.getToken( 0, ';', nIndex ) };
+
+ // Exactly 3 tokens are required
+ if (bTooFewTokens || nIndex>0)
+ {
+ throw RuntimeException("illegal uno url given!" );
+ }
+
+ Reference< XAcceptor > xAcceptor = Acceptor::create(xContext);
+
+ // init params
+ Sequence< Any > aInitParams( aParams.getLength() );
+ const OUString * p = aParams.getConstArray();
+ Any * pInitParams = aInitParams.getArray();
+ for ( sal_Int32 i = aParams.getLength(); i--; )
+ {
+ pInitParams[i] <<= p[i];
+ }
+
+ // instance provider
+ Reference< XInstanceProvider > xInstanceProvider( new OInstanceProvider(
+ xContext, aImplName, aLocation, aServiceName, aInitParams,
+ bSingleInstance, aInstanceName ) );
+
+ // coverity[loop_top] - not really an infinite loop, we can be instructed to exit via the connection
+ for (;;)
+ {
+ // accepting
+ out( "\n> accepting " );
+ out( aConnectDescr );
+ out( "..." );
+ Reference< XConnection > xConnection( xAcceptor->accept( aConnectDescr ) );
+ out( "connection established." );
+
+ Reference< XBridgeFactory > xBridgeFactory;
+ createInstance(
+ xBridgeFactory, xContext,
+ "com.sun.star.bridge.BridgeFactory" );
+
+ // bridge
+ Reference< XBridge > xBridge( xBridgeFactory->createBridge(
+ OUString(), aUnoUrlToken,
+ xConnection, xInstanceProvider ) );
+
+ if (bSingleAccept)
+ {
+ Reference< XComponent > xComp( xBridge, UNO_QUERY_THROW );
+ ODisposingListener::waitFor( xComp );
+ xComp->dispose();
+ // explicitly dispose the remote bridge so that it joins
+ // on all spawned threads before process exit (see
+ // binaryurp/source/bridge.cxx for details)
+ break;
+ }
+ }
+ }
+ else // no uno url
+ {
+ Reference< XInterface > xInstance;
+ if (!aImplName.isEmpty()) // manually via loader
+ xInstance = loadComponent( xContext, aImplName, aLocation );
+ else // via service manager
+ createInstance( xInstance, xContext, aServiceName );
+
+ // execution
+ Reference< XMain > xMain( xInstance, UNO_QUERY );
+ if (xMain.is())
+ {
+ nRet = xMain->run( aParams );
+ }
+ else
+ {
+ Reference< XComponent > xComp( xInstance, UNO_QUERY );
+ if (xComp.is())
+ xComp->dispose();
+ throw RuntimeException( "component does not export interface \"com.sun.star.lang.XMain\"!" );
+ }
+ }
+ }
+ catch (Exception & rExc)
+ {
+ out( "\n> error: " );
+ out( rExc.Message );
+ out( "\n> dying..." );
+ nRet = 1;
+ }
+
+ // cleanup
+ Reference< XComponent > xComp( xContext, UNO_QUERY );
+ if (xComp.is())
+ xComp->dispose();
+
+ return nRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */