summaryrefslogtreecommitdiffstats
path: root/codemaker/source/cppumaker/cpputype.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'codemaker/source/cppumaker/cpputype.cxx')
-rw-r--r--codemaker/source/cppumaker/cpputype.cxx4105
1 files changed, 4105 insertions, 0 deletions
diff --git a/codemaker/source/cppumaker/cpputype.cxx b/codemaker/source/cppumaker/cpputype.cxx
new file mode 100644
index 000000000..03fcd033b
--- /dev/null
+++ b/codemaker/source/cppumaker/cpputype.cxx
@@ -0,0 +1,4105 @@
+/* -*- 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 <algorithm>
+#include <cassert>
+#include <cstdlib>
+#include <map>
+#include <set>
+#include <string_view>
+#include <memory>
+#include <utility>
+#include <vector>
+#include <iostream>
+
+#include <rtl/alloc.h>
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/strbuf.hxx>
+#include <unoidl/unoidl.hxx>
+
+#include <codemaker/commoncpp.hxx>
+#include <codemaker/exceptiontree.hxx>
+#include <codemaker/generatedtypeset.hxx>
+#include <codemaker/typemanager.hxx>
+#include <codemaker/unotype.hxx>
+
+#include "cpputype.hxx"
+#include "cppuoptions.hxx"
+#include "dependencies.hxx"
+#include "dumputils.hxx"
+#include "includes.hxx"
+
+namespace
+{
+
+bool isBootstrapType(OUString const & name)
+{
+ static char const * const names[] = {
+ "com.sun.star.beans.Property",
+ "com.sun.star.beans.PropertyAttribute",
+ "com.sun.star.beans.PropertyChangeEvent",
+ "com.sun.star.beans.PropertyState",
+ "com.sun.star.beans.PropertyValue",
+ "com.sun.star.beans.XFastPropertySet",
+ "com.sun.star.beans.XMultiPropertySet",
+ "com.sun.star.beans.XPropertiesChangeListener",
+ "com.sun.star.beans.XPropertyAccess",
+ "com.sun.star.beans.XPropertyChangeListener",
+ "com.sun.star.beans.XPropertySet",
+ "com.sun.star.beans.XPropertySetInfo",
+ "com.sun.star.beans.XPropertySetOption",
+ "com.sun.star.beans.XVetoableChangeListener",
+ "com.sun.star.bridge.UnoUrlResolver",
+ "com.sun.star.bridge.XUnoUrlResolver",
+ "com.sun.star.connection.SocketPermission",
+ "com.sun.star.container.XElementAccess",
+ "com.sun.star.container.XEnumeration",
+ "com.sun.star.container.XEnumerationAccess",
+ "com.sun.star.container.XHierarchicalNameAccess",
+ "com.sun.star.container.XNameAccess",
+ "com.sun.star.container.XNameContainer",
+ "com.sun.star.container.XNameReplace",
+ "com.sun.star.container.XSet",
+ "com.sun.star.io.FilePermission",
+ "com.sun.star.io.IOException",
+ "com.sun.star.lang.DisposedException",
+ "com.sun.star.lang.EventObject",
+ "com.sun.star.lang.WrappedTargetRuntimeException",
+ "com.sun.star.lang.XComponent",
+ "com.sun.star.lang.XEventListener",
+ "com.sun.star.lang.XInitialization",
+ "com.sun.star.lang.XMultiComponentFactory",
+ "com.sun.star.lang.XMultiServiceFactory",
+ "com.sun.star.lang.XServiceInfo",
+ "com.sun.star.lang.XSingleComponentFactory",
+ "com.sun.star.lang.XSingleServiceFactory",
+ "com.sun.star.lang.XTypeProvider",
+ "com.sun.star.loader.XImplementationLoader",
+ "com.sun.star.reflection.FieldAccessMode",
+ "com.sun.star.reflection.MethodMode",
+ "com.sun.star.reflection.ParamInfo",
+ "com.sun.star.reflection.ParamMode",
+ "com.sun.star.reflection.TypeDescriptionSearchDepth",
+ "com.sun.star.reflection.XCompoundTypeDescription",
+ "com.sun.star.reflection.XEnumTypeDescription",
+ "com.sun.star.reflection.XIdlArray",
+ "com.sun.star.reflection.XIdlClass",
+ "com.sun.star.reflection.XIdlField",
+ "com.sun.star.reflection.XIdlField2",
+ "com.sun.star.reflection.XIdlMethod",
+ "com.sun.star.reflection.XIdlReflection",
+ "com.sun.star.reflection.XIndirectTypeDescription",
+ "com.sun.star.reflection.XInterfaceAttributeTypeDescription",
+ "com.sun.star.reflection.XInterfaceAttributeTypeDescription2",
+ "com.sun.star.reflection.XInterfaceMemberTypeDescription",
+ "com.sun.star.reflection.XInterfaceMethodTypeDescription",
+ "com.sun.star.reflection.XInterfaceTypeDescription",
+ "com.sun.star.reflection.XInterfaceTypeDescription2",
+ "com.sun.star.reflection.XMethodParameter",
+ "com.sun.star.reflection.XStructTypeDescription",
+ "com.sun.star.reflection.XTypeDescription",
+ "com.sun.star.reflection.XTypeDescriptionEnumeration",
+ "com.sun.star.reflection.XTypeDescriptionEnumerationAccess",
+ "com.sun.star.registry.RegistryKeyType",
+ "com.sun.star.registry.RegistryValueType",
+ "com.sun.star.registry.XImplementationRegistration",
+ "com.sun.star.registry.XRegistryKey",
+ "com.sun.star.registry.XSimpleRegistry",
+ "com.sun.star.security.RuntimePermission",
+ "com.sun.star.security.XAccessControlContext",
+ "com.sun.star.security.XAccessController",
+ "com.sun.star.security.XAction",
+ "com.sun.star.uno.DeploymentException",
+ "com.sun.star.uno.RuntimeException",
+ "com.sun.star.uno.TypeClass",
+ "com.sun.star.uno.Uik",
+ "com.sun.star.uno.XAdapter",
+ "com.sun.star.uno.XAggregation",
+ "com.sun.star.uno.XComponentContext",
+ "com.sun.star.uno.XCurrentContext",
+ "com.sun.star.uno.XInterface",
+ "com.sun.star.uno.XReference",
+ "com.sun.star.uno.XUnloadingPreference",
+ "com.sun.star.uno.XWeak",
+ "com.sun.star.util.XMacroExpander" };
+ // cf. cppuhelper/unotypes/Makefile UNOTYPES (plus missing dependencies)
+ auto const pred = [&name](const char* aName) {
+ return name.equalsAscii(aName);
+ };
+ return std::any_of(std::begin(names), std::end(names), pred);
+}
+
+class CppuType
+{
+public:
+ CppuType(OUString name, rtl::Reference< TypeManager > const & typeMgr);
+
+ virtual ~CppuType() {}
+
+ CppuType(const CppuType&) = delete;
+ const CppuType& operator=(const CppuType&) = delete;
+
+ void dump(CppuOptions const & options);
+
+ void dumpFile(
+ std::u16string_view uri, std::u16string_view name, bool hpp,
+ CppuOptions const & options);
+
+ void dumpDependedTypes(
+ codemaker::GeneratedTypeSet & generated, CppuOptions const & options) const;
+
+ virtual void dumpHdlFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes) {
+ dumpHFileContent(out, includes);
+ }
+
+ virtual void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) = 0;
+
+ OUString dumpHeaderDefine(FileStream& o, std::u16string_view extension) const;
+
+ void dumpGetCppuType(FileStream & out);
+
+ virtual void dumpLightGetCppuType(FileStream & out);
+
+ virtual void dumpNormalGetCppuType(FileStream &) {
+ assert(false); // this cannot happen
+ }
+
+ virtual void dumpComprehensiveGetCppuType(FileStream &) {
+ assert(false); // this cannot happen
+ }
+
+ void dumpType(
+ FileStream & out, std::u16string_view name, bool isConst = false,
+ bool isRef = false, bool native = false, bool cppuUnoType = false)
+ const;
+
+ OUString getTypeClass(OUString const & name, bool cStyle = false);
+
+ void dumpCppuGetType(
+ FileStream & out, std::u16string_view name, OUString const * ownName = nullptr) const;
+
+ sal_uInt32 getInheritedMemberCount();
+
+ void inc(sal_Int32 num=4);
+ void dec(sal_Int32 num=4);
+ OUString indent() const;
+protected:
+ virtual sal_uInt32 checkInheritedMemberCount() const {
+ assert(false); // this cannot happen
+ return 0;
+ }
+
+ bool passByReference(OUString const & name) const;
+
+ bool canBeWarnUnused(OUString const & name) const;
+ bool canBeWarnUnused(OUString const & name, int depth) const;
+
+ OUString resolveOuterTypedefs(OUString const & name) const;
+
+ OUString resolveAllTypedefs(std::u16string_view name) const;
+
+ codemaker::cpp::IdentifierTranslationMode isGlobal() const;
+
+ virtual void dumpDeclaration(FileStream &) {
+ assert(false); // this cannot happen
+ }
+
+ virtual void dumpFiles(OUString const & uri, CppuOptions const & options);
+
+ virtual void addLightGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const;
+
+ virtual void addNormalGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const;
+
+ virtual void addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const;
+
+ virtual bool isPolymorphic() const;
+
+ virtual void dumpTemplateHead(FileStream &) const {}
+
+ virtual void dumpTemplateParameters(FileStream &) const {}
+
+ void dumpGetCppuTypePreamble(FileStream & out);
+
+ void dumpGetCppuTypePostamble(FileStream & out);
+
+ void addDefaultHIncludes(codemaker::cppumaker::Includes & includes) const;
+ void addDefaultHxxIncludes(codemaker::cppumaker::Includes & includes) const;
+
+ void dumpInitializer(
+ FileStream & out, bool parameterized, std::u16string_view name) const;
+
+ void dumpHFileContent(
+ FileStream & out, codemaker::cppumaker::Includes & includes);
+
+protected:
+ sal_uInt32 m_inheritedMemberCount;
+
+ bool m_cppuTypeLeak;
+ bool m_cppuTypeDynamic;
+ sal_Int32 m_indentLength;
+ OUString name_;
+ OUString id_;
+ rtl::Reference< TypeManager > m_typeMgr;
+ codemaker::cppumaker::Dependencies m_dependencies;
+
+private:
+ void addGetCppuTypeIncludes(codemaker::cppumaker::Includes & includes)
+ const;
+};
+
+CppuType::CppuType(
+ OUString name, rtl::Reference< TypeManager > const & typeMgr):
+ m_inheritedMemberCount(0)
+ , m_cppuTypeLeak(false)
+ , m_cppuTypeDynamic(true)
+ , m_indentLength(0)
+ , name_(std::move(name))
+ , id_(name_.copy(name_.lastIndexOf('.') + 1))
+ , m_typeMgr(typeMgr)
+ , m_dependencies(typeMgr, name_)
+{}
+
+void CppuType::addGetCppuTypeIncludes(codemaker::cppumaker::Includes & includes)
+const
+{
+ if (name_ == "com.sun.star.uno.XInterface"
+ || name_ == "com.sun.star.uno.Exception") {
+ includes.addType();
+ includes.addCppuUnotypeHxx();
+ includes.addSalTypesH();
+ includes.addTypelibTypeclassH();
+ includes.addTypelibTypedescriptionH();
+ } else if (m_cppuTypeLeak) {
+ addLightGetCppuTypeIncludes(includes);
+ } else if (m_cppuTypeDynamic) {
+ addNormalGetCppuTypeIncludes(includes);
+ } else {
+ addComprehensiveGetCppuTypeIncludes(includes);
+ }
+}
+
+void CppuType::dumpFiles(OUString const & uri, CppuOptions const & options)
+{
+ dumpFile(uri, name_, false, options);
+ dumpFile(uri, name_, true, options);
+}
+
+void CppuType::addLightGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ //TODO: Determine what is really needed, instead of relying on
+ // addDefaultHxxIncludes
+ includes.addCppuUnotypeHxx();
+}
+
+void CppuType::addNormalGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ //TODO: Determine what is really needed, instead of relying on
+ // addDefaultHxxIncludes
+ includes.addCppuUnotypeHxx();
+}
+
+void CppuType::addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ //TODO: Determine what is really needed, instead of relying on
+ // addDefaultHxxIncludes
+ includes.addCppuUnotypeHxx();
+}
+
+bool CppuType::isPolymorphic() const
+{
+ return false;
+}
+
+void CppuType::dumpGetCppuTypePreamble(FileStream & out)
+{
+ if (isPolymorphic()) {
+ out << "namespace cppu {\n\n";
+ dumpTemplateHead(out);
+ out << "class UnoType< ";
+ dumpType(out, name_);
+ dumpTemplateParameters(out);
+ out << " > {\npublic:\n";
+ inc();
+ out << indent()
+ << "static inline ::css::uno::Type const & get() {\n";
+ } else {
+ if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) {
+ out << "\n\n";
+ }
+ out << ("inline ::css::uno::Type const &"
+ " cppu_detail_getUnoType(SAL_UNUSED_PARAMETER ");
+ dumpType(out, name_, false, false, true);
+ out << " const *) {\n";
+ }
+ inc();
+}
+
+void CppuType::dumpGetCppuTypePostamble(FileStream & out)
+{
+ dec();
+ if (isPolymorphic()) {
+ out << indent() << "}\n\nprivate:\n"
+ << indent() << "UnoType(UnoType &); // not defined\n"
+ << indent() << "~UnoType(); // not defined\n"
+ << indent()
+ << "void operator =(UnoType); // not defined\n};\n\n}\n\n";
+ } else {
+ out << "}\n\n";
+ if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) {
+ out << "\n\n";
+ }
+ }
+ dumpTemplateHead(out);
+ out << ("SAL_DEPRECATED(\"use cppu::UnoType\") inline ::css::uno::Type const & SAL_CALL"
+ " getCppuType(SAL_UNUSED_PARAMETER ");
+ dumpType(out, name_);
+ dumpTemplateParameters(out);
+ out << " const *) {\n";
+ inc();
+ out << indent() << "return ::cppu::UnoType< ";
+ dumpType(out, name_);
+ dumpTemplateParameters(out);
+ out << " >::get();\n";
+ dec();
+ out << indent() << "}\n";
+}
+
+void CppuType::dump(CppuOptions const & options)
+{
+ if (isBootstrapType(name_)) {
+ m_cppuTypeDynamic = false;
+ } else {
+ // -CS was used as an undocumented option to generate static getCppuType
+ // functions; since the introduction of cppu::UnoType this no longer is
+ // meaningful (getCppuType is just a forward to cppu::UnoType::get now),
+ // and -CS is handled the same way as -C now:
+ if (options.isValid("-L"))
+ m_cppuTypeLeak = true;
+ if (options.isValid("-C") || options.isValid("-CS"))
+ m_cppuTypeDynamic = false;
+ }
+ dumpFiles(
+ options.isValid("-O") ? b2u(options.getOption("-O")) : "", options);
+}
+
+void CppuType::dumpFile(
+ std::u16string_view uri, std::u16string_view name, bool hpp,
+ CppuOptions const & options)
+{
+ OUString fileUri(
+ b2u(createFileNameFromType(
+ u2b(uri), u2b(name), hpp ? ".hpp" : ".hdl")));
+ if (fileUri.isEmpty()) {
+ throw CannotDumpException(OUString::Concat("empty target URI for entity ") + name);
+ }
+ bool exists = fileExists(u2b(fileUri));
+ if (exists && options.isValid("-G")) {
+ return;
+ }
+ FileStream out;
+ out.createTempFile(getTempDir(u2b(fileUri)));
+ OUString tmpUri(b2u(out.getName()));
+ if(!out.isValid()) {
+ throw CannotDumpException("cannot open " + tmpUri + " for writing");
+ }
+ codemaker::cppumaker::Includes includes(m_typeMgr, m_dependencies, hpp);
+ try {
+ if (hpp) {
+ addGetCppuTypeIncludes(includes);
+ dumpHppFile(out, includes);
+ } else {
+ dumpHdlFile(out, includes);
+ }
+ } catch (...) {
+ out.close();
+ // Remove existing type file if something goes wrong to ensure
+ // consistency:
+ if (fileExists(u2b(fileUri))) {
+ removeTypeFile(u2b(fileUri));
+ }
+ removeTypeFile(u2b(tmpUri));
+ throw;
+ }
+ out.close();
+ (void)makeValidTypeFile(
+ u2b(fileUri), u2b(tmpUri), exists && options.isValid("-Gc"));
+}
+
+void CppuType::dumpDependedTypes(
+ codemaker::GeneratedTypeSet & generated, CppuOptions const & options) const
+{
+ if (!options.isValid("-nD")) {
+ codemaker::cppumaker::Dependencies::Map const & map
+ = m_dependencies.getMap();
+ for (const auto& entry : map) {
+ produce(entry.first, m_typeMgr, generated, options);
+ }
+ }
+}
+
+OUString CppuType::dumpHeaderDefine(
+ FileStream & out, std::u16string_view extension) const
+{
+ OUString def(
+ "INCLUDED_" + name_.replace('.', '_').toAsciiUpperCase() + "_"
+ + extension);
+ out << "#ifndef " << def << "\n#define " << def << "\n";
+ return def;
+}
+
+void CppuType::addDefaultHIncludes(codemaker::cppumaker::Includes & includes)
+const
+{
+ //TODO: Only include what is really needed
+ includes.addCppuMacrosHxx();
+ if (m_typeMgr->getSort(name_)
+ == codemaker::UnoType::Sort::Interface) {
+ includes.addReference();
+ }
+}
+
+void CppuType::addDefaultHxxIncludes(codemaker::cppumaker::Includes & includes)
+const
+{
+ //TODO: Only include what is really needed
+ includes.addType();
+ if (m_typeMgr->getSort(name_)
+ == codemaker::UnoType::Sort::Interface) {
+ includes.addReference();
+ }
+}
+
+void CppuType::dumpInitializer(
+ FileStream & out, bool parameterized, std::u16string_view name) const
+{
+ out << "(";
+ if (!parameterized) {
+ sal_Int32 k;
+ std::vector< OString > args;
+ OUString n(
+ b2u(codemaker::UnoType::decompose(
+ u2b(resolveAllTypedefs(name)), &k, &args)));
+ if (k == 0) {
+ rtl::Reference< unoidl::Entity > ent;
+ switch (m_typeMgr->getSort(n, &ent)) {
+ case codemaker::UnoType::Sort::Boolean:
+ out << "false";
+ break;
+ case codemaker::UnoType::Sort::Byte:
+ case codemaker::UnoType::Sort::Short:
+ case codemaker::UnoType::Sort::UnsignedShort:
+ case codemaker::UnoType::Sort::Long:
+ case codemaker::UnoType::Sort::UnsignedLong:
+ case codemaker::UnoType::Sort::Hyper:
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ case codemaker::UnoType::Sort::Float:
+ case codemaker::UnoType::Sort::Double:
+ case codemaker::UnoType::Sort::Char:
+ out << "0";
+ break;
+ case codemaker::UnoType::Sort::Enum:
+ out << codemaker::cpp::scopedCppName(u2b(n)) << "_"
+ << (dynamic_cast<unoidl::EnumTypeEntity&>(*ent).
+ getMembers()[0].name);
+ break;
+ case codemaker::UnoType::Sort::String:
+ case codemaker::UnoType::Sort::Type:
+ case codemaker::UnoType::Sort::Any:
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::PolymorphicStructTemplate:
+ case codemaker::UnoType::Sort::Interface:
+ break;
+ default:
+ throw CannotDumpException(
+ OUString::Concat("unexpected entity \"") + name
+ + "\" in call to CppuType::dumpInitializer");
+ }
+ }
+ }
+ out << ")";
+}
+
+void CppuType::dumpHFileContent(
+ FileStream & out, codemaker::cppumaker::Includes & includes)
+{
+ addDefaultHIncludes(includes);
+ dumpHeaderDefine(out, u"HDL");
+ out << "\n";
+ includes.dump(out, nullptr, false);
+ // 'exceptions = false' would be wrong for services/singletons, but
+ // those don't dump .hdl files anyway
+ out << ("\nnamespace com { namespace sun { namespace star { namespace uno"
+ " { class Type; } } } }\n\n");
+ if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) {
+ out << "\n";
+ }
+ dumpDeclaration(out);
+ if (!(name_ == "com.sun.star.uno.XInterface"
+ || name_ == "com.sun.star.uno.Exception"
+ || isPolymorphic())) {
+ out << "\n" << indent()
+ << ("inline ::css::uno::Type const &"
+ " cppu_detail_getUnoType(SAL_UNUSED_PARAMETER ");
+ dumpType(out, name_, false, false, true);
+ out << " const *);\n";
+ }
+ if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) {
+ out << "\n";
+ }
+ out << "\n";
+ dumpTemplateHead(out);
+ out << "SAL_DEPRECATED(\"use cppu::UnoType\") inline ::css::uno::Type const & SAL_CALL getCppuType(";
+ dumpType(out, name_, true);
+ dumpTemplateParameters(out);
+ out << " *);\n\n#endif\n";
+}
+
+void CppuType::dumpGetCppuType(FileStream & out)
+{
+ if (name_ == "com.sun.star.uno.XInterface") {
+ out << indent()
+ << ("SAL_DEPRECATED(\"use cppu::UnoType\") inline ::css::uno::Type const & SAL_CALL"
+ " getCppuType(SAL_UNUSED_PARAMETER ");
+ dumpType(out, name_, true);
+ out << " *) {\n";
+ inc();
+ out << indent()
+ << ("return ::cppu::UnoType< ::css::uno::XInterface"
+ " >::get();\n");
+ dec();
+ out << indent() << "}\n";
+ } else if (name_ == "com.sun.star.uno.Exception") {
+ out << indent()
+ << ("SAL_DEPRECATED(\"use cppu::UnoType\") inline ::css::uno::Type const & SAL_CALL"
+ " getCppuType(SAL_UNUSED_PARAMETER ");
+ dumpType(out, name_, true);
+ out << " *) {\n";
+ inc();
+ out << indent()
+ << ("return ::cppu::UnoType< ::css::uno::Exception"
+ " >::get();\n");
+ dec();
+ out << indent() << "}\n";
+ } else if (m_cppuTypeLeak) {
+ dumpLightGetCppuType(out);
+ } else if (m_cppuTypeDynamic) {
+ dumpNormalGetCppuType(out);
+ } else {
+ dumpComprehensiveGetCppuType(out);
+ }
+}
+
+void CppuType::dumpLightGetCppuType(FileStream & out)
+{
+ dumpGetCppuTypePreamble(out);
+ out << indent()
+ << "static typelib_TypeDescriptionReference * the_type = 0;\n"
+ << indent() << "if ( !the_type )\n" << indent() << "{\n";
+ inc();
+ out << indent() << "typelib_static_type_init( &the_type, "
+ << getTypeClass(name_, true) << ", \"" << name_ << "\" );\n";
+ dec();
+ out << indent() << "}\n" << indent()
+ << ("return * reinterpret_cast< ::css::uno::Type * >("
+ " &the_type );\n");
+ dumpGetCppuTypePostamble(out);
+}
+
+codemaker::cpp::IdentifierTranslationMode CppuType::isGlobal() const
+{
+ return name_.indexOf('.') == -1
+ ? codemaker::cpp::IdentifierTranslationMode::Global : codemaker::cpp::IdentifierTranslationMode::NonGlobal;
+}
+
+sal_uInt32 CppuType::getInheritedMemberCount()
+{
+ if (m_inheritedMemberCount == 0) {
+ m_inheritedMemberCount = checkInheritedMemberCount();
+ }
+
+ return m_inheritedMemberCount;
+}
+
+OUString CppuType::getTypeClass(OUString const & name, bool cStyle)
+{
+ rtl::Reference< unoidl::Entity > ent;
+ switch (m_typeMgr->getSort(name, &ent)) {
+ case codemaker::UnoType::Sort::Void:
+ return cStyle
+ ? OUString("typelib_TypeClass_VOID")
+ : OUString("::css::uno::TypeClass_VOID");
+ case codemaker::UnoType::Sort::Boolean:
+ return cStyle
+ ? OUString("typelib_TypeClass_BOOLEAN")
+ : OUString("::css::uno::TypeClass_BOOLEAN");
+ case codemaker::UnoType::Sort::Byte:
+ return cStyle
+ ? OUString("typelib_TypeClass_BYTE")
+ : OUString("::css::uno::TypeClass_BYTE");
+ case codemaker::UnoType::Sort::Short:
+ return cStyle
+ ? OUString("typelib_TypeClass_SHORT")
+ : OUString("::css::uno::TypeClass_SHORT");
+ case codemaker::UnoType::Sort::UnsignedShort:
+ return cStyle
+ ? OUString("typelib_TypeClass_UNSIGNED_SHORT")
+ : OUString("::css::uno::TypeClass_UNSIGNED_SHORT");
+ case codemaker::UnoType::Sort::Long:
+ return cStyle
+ ? OUString("typelib_TypeClass_LONG")
+ : OUString("::css::uno::TypeClass_LONG");
+ case codemaker::UnoType::Sort::UnsignedLong:
+ return cStyle
+ ? OUString("typelib_TypeClass_UNSIGNED_LONG")
+ : OUString("::css::uno::TypeClass_UNSIGNED_LONG");
+ case codemaker::UnoType::Sort::Hyper:
+ return cStyle
+ ? OUString("typelib_TypeClass_HYPER")
+ : OUString("::css::uno::TypeClass_HYPER");
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ return cStyle
+ ? OUString("typelib_TypeClass_UNSIGNED_HYPER")
+ : OUString("::css::uno::TypeClass_UNSIGNED_HYPER");
+ case codemaker::UnoType::Sort::Float:
+ return cStyle
+ ? OUString("typelib_TypeClass_FLOAT")
+ : OUString("::css::uno::TypeClass_FLOAT");
+ case codemaker::UnoType::Sort::Double:
+ return cStyle
+ ? OUString("typelib_TypeClass_DOUBLE")
+ : OUString("::css::uno::TypeClass_DOUBLE");
+ case codemaker::UnoType::Sort::Char:
+ return cStyle
+ ? OUString("typelib_TypeClass_CHAR")
+ : OUString("::css::uno::TypeClass_CHAR");
+ case codemaker::UnoType::Sort::String:
+ return cStyle
+ ? OUString("typelib_TypeClass_STRING")
+ : OUString("::css::uno::TypeClass_STRING");
+ case codemaker::UnoType::Sort::Type:
+ return cStyle
+ ? OUString("typelib_TypeClass_TYPE")
+ : OUString("::css::uno::TypeClass_TYPE");
+ case codemaker::UnoType::Sort::Any:
+ return cStyle
+ ? OUString("typelib_TypeClass_ANY")
+ : OUString("::css::uno::TypeClass_ANY");
+ case codemaker::UnoType::Sort::Sequence:
+ return cStyle
+ ? OUString("typelib_TypeClass_SEQUENCE")
+ : OUString("::css::uno::TypeClass_SEQUENCE");
+ case codemaker::UnoType::Sort::Enum:
+ return cStyle
+ ? OUString("typelib_TypeClass_ENUM")
+ : OUString("::css::uno::TypeClass_ENUM");
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::PolymorphicStructTemplate:
+ case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
+ return cStyle
+ ? OUString("typelib_TypeClass_STRUCT")
+ : OUString("::css::uno::TypeClass_STRUCT");
+ case codemaker::UnoType::Sort::Exception:
+ return cStyle
+ ? OUString("typelib_TypeClass_EXCEPTION")
+ : OUString("::css::uno::TypeClass_EXCEPTION");
+ case codemaker::UnoType::Sort::Interface:
+ return cStyle
+ ? OUString("typelib_TypeClass_INTERFACE")
+ : OUString("::css::uno::TypeClass_INTERFACE");
+ case codemaker::UnoType::Sort::Typedef:
+ return getTypeClass(dynamic_cast<unoidl::TypedefEntity&>(*ent).getType(), cStyle);
+ default:
+ for (;;) {
+ std::abort();
+ }
+ }
+}
+
+void CppuType::dumpType(
+ FileStream & out, std::u16string_view name, bool isConst, bool isRef,
+ bool native, bool cppuUnoType) const
+{
+ sal_Int32 k;
+ std::vector< OString > args;
+ OUString n(
+ b2u(codemaker::UnoType::decompose(
+ u2b(resolveAllTypedefs(name)), &k, &args)));
+ if (isConst) {
+ out << "const ";
+ }
+ for (sal_Int32 i = 0; i != k; ++i) {
+ out << (cppuUnoType
+ ? "::cppu::UnoSequenceType" : "::css::uno::Sequence")
+ << "< ";
+ }
+ switch (m_typeMgr->getSort(n)) {
+ case codemaker::UnoType::Sort::Void:
+ out << "void";
+ break;
+ case codemaker::UnoType::Sort::Boolean:
+ out << "::sal_Bool";
+ break;
+ case codemaker::UnoType::Sort::Byte:
+ out << "::sal_Int8";
+ break;
+ case codemaker::UnoType::Sort::Short:
+ out << "::sal_Int16";
+ break;
+ case codemaker::UnoType::Sort::UnsignedShort:
+ out << (cppuUnoType ? "::cppu::UnoUnsignedShortType" : "::sal_uInt16");
+ break;
+ case codemaker::UnoType::Sort::Long:
+ out << "::sal_Int32";
+ break;
+ case codemaker::UnoType::Sort::UnsignedLong:
+ out << "::sal_uInt32";
+ break;
+ case codemaker::UnoType::Sort::Hyper:
+ out << "::sal_Int64";
+ break;
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ out << "::sal_uInt64";
+ break;
+ case codemaker::UnoType::Sort::Float:
+ out << "float";
+ break;
+ case codemaker::UnoType::Sort::Double:
+ out << "double";
+ break;
+ case codemaker::UnoType::Sort::Char:
+ out << (cppuUnoType ? "::cppu::UnoCharType" : "::sal_Unicode");
+ break;
+ case codemaker::UnoType::Sort::String:
+ out << "::rtl::OUString";
+ break;
+ case codemaker::UnoType::Sort::Type:
+ out << "::css::uno::Type";
+ break;
+ case codemaker::UnoType::Sort::Any:
+ out << "::css::uno::Any";
+ break;
+ case codemaker::UnoType::Sort::Enum:
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::Exception:
+ out << codemaker::cpp::scopedCppName(u2b(n));
+ break;
+ case codemaker::UnoType::Sort::PolymorphicStructTemplate:
+ out << codemaker::cpp::scopedCppName(u2b(n));
+ if (!args.empty()) {
+ out << "< ";
+ for (std::vector< OString >::iterator i(args.begin());
+ i != args.end(); ++i) {
+ if (i != args.begin()) {
+ out << ", ";
+ }
+ dumpType(out, b2u(*i));
+ }
+ out << " >";
+ }
+ break;
+ case codemaker::UnoType::Sort::Interface:
+ if (!native) {
+ out << "::css::uno::Reference< ";
+ }
+ out << codemaker::cpp::scopedCppName(u2b(n));
+ if (!native) {
+ out << " >";
+ }
+ break;
+ default:
+ throw CannotDumpException(
+ OUString::Concat("unexpected entity \"") + name + "\" in call to CppuType::dumpType");
+ }
+ for (sal_Int32 i = 0; i != k; ++i) {
+ out << " >";
+ }
+ if (isRef) {
+ out << "&";
+ }
+}
+
+void CppuType::dumpCppuGetType(
+ FileStream & out, std::u16string_view name, OUString const * ownName) const
+{
+ //TODO: What are these calls good for?
+ OUString nucleus;
+ sal_Int32 rank;
+ codemaker::UnoType::Sort sort = m_typeMgr->decompose(
+ name, true, &nucleus, &rank, nullptr, nullptr);
+ switch (rank == 0 ? sort : codemaker::UnoType::Sort::Sequence) {
+ case codemaker::UnoType::Sort::Void:
+ case codemaker::UnoType::Sort::Boolean:
+ case codemaker::UnoType::Sort::Byte:
+ case codemaker::UnoType::Sort::Short:
+ case codemaker::UnoType::Sort::UnsignedShort:
+ case codemaker::UnoType::Sort::Long:
+ case codemaker::UnoType::Sort::UnsignedLong:
+ case codemaker::UnoType::Sort::Hyper:
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ case codemaker::UnoType::Sort::Float:
+ case codemaker::UnoType::Sort::Double:
+ case codemaker::UnoType::Sort::Char:
+ case codemaker::UnoType::Sort::String:
+ case codemaker::UnoType::Sort::Type:
+ case codemaker::UnoType::Sort::Any:
+ break;
+ case codemaker::UnoType::Sort::Sequence:
+ case codemaker::UnoType::Sort::Enum:
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
+ case codemaker::UnoType::Sort::Exception:
+ case codemaker::UnoType::Sort::Interface:
+ // Take care of recursion like struct S { sequence<S> x; }:
+ if (ownName == nullptr || nucleus != *ownName) {
+ out << indent() << "::cppu::UnoType< ";
+ dumpType(out, name, false, false, false, true);
+ out << " >::get();\n";
+ }
+ break;
+ case codemaker::UnoType::Sort::Typedef:
+ for (;;) std::abort(); // this cannot happen
+ default:
+ throw CannotDumpException(
+ OUString::Concat("unexpected entity \"") + name
+ + "\" in call to CppuType::dumpCppuGetType");
+ }
+}
+
+bool CppuType::passByReference(OUString const & name) const
+{
+ switch (m_typeMgr->getSort(resolveOuterTypedefs(name))) {
+ case codemaker::UnoType::Sort::Boolean:
+ case codemaker::UnoType::Sort::Byte:
+ case codemaker::UnoType::Sort::Short:
+ case codemaker::UnoType::Sort::UnsignedShort:
+ case codemaker::UnoType::Sort::Long:
+ case codemaker::UnoType::Sort::UnsignedLong:
+ case codemaker::UnoType::Sort::Hyper:
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ case codemaker::UnoType::Sort::Float:
+ case codemaker::UnoType::Sort::Double:
+ case codemaker::UnoType::Sort::Char:
+ case codemaker::UnoType::Sort::Enum:
+ return false;
+ case codemaker::UnoType::Sort::String:
+ case codemaker::UnoType::Sort::Type:
+ case codemaker::UnoType::Sort::Any:
+ case codemaker::UnoType::Sort::Sequence:
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
+ case codemaker::UnoType::Sort::Interface:
+ return true;
+ default:
+ throw CannotDumpException(
+ "unexpected entity \"" + name
+ + "\" in call to CppuType::passByReference");
+ }
+}
+
+bool CppuType::canBeWarnUnused(OUString const & name) const
+{
+ return canBeWarnUnused(name, 0);
+}
+bool CppuType::canBeWarnUnused(OUString const & name, int depth) const
+{
+ // prevent infinite recursion and blowing the stack
+ if (depth > 10)
+ return false;
+ OUString aResolvedName = resolveOuterTypedefs(name);
+ switch (m_typeMgr->getSort(aResolvedName)) {
+ case codemaker::UnoType::Sort::Boolean:
+ case codemaker::UnoType::Sort::Byte:
+ case codemaker::UnoType::Sort::Short:
+ case codemaker::UnoType::Sort::UnsignedShort:
+ case codemaker::UnoType::Sort::Long:
+ case codemaker::UnoType::Sort::UnsignedLong:
+ case codemaker::UnoType::Sort::Hyper:
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ case codemaker::UnoType::Sort::Float:
+ case codemaker::UnoType::Sort::Double:
+ case codemaker::UnoType::Sort::Char:
+ case codemaker::UnoType::Sort::Enum:
+ case codemaker::UnoType::Sort::String:
+ case codemaker::UnoType::Sort::Type:
+ return true;
+ case codemaker::UnoType::Sort::PlainStruct: {
+ rtl::Reference< unoidl::Entity > ent;
+ m_typeMgr->getSort(aResolvedName, &ent);
+ rtl::Reference< unoidl::PlainStructTypeEntity > ent2(
+ dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get()));
+ if (!ent2->getDirectBase().isEmpty() && !canBeWarnUnused(ent2->getDirectBase(), depth+1))
+ return false;
+ for ( const unoidl::PlainStructTypeEntity::Member& rMember : ent2->getDirectMembers()) {
+ if (!canBeWarnUnused(rMember.type, depth+1))
+ return false;
+ }
+ return true;
+ }
+ case codemaker::UnoType::Sort::Sequence: {
+ OUString aInnerType = aResolvedName.copy(2);
+ return canBeWarnUnused(aInnerType, depth+1);
+ }
+ case codemaker::UnoType::Sort::Any:
+ case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
+ case codemaker::UnoType::Sort::Interface:
+ return false;
+ default:
+ throw CannotDumpException(
+ "unexpected entity \"" + name
+ + "\" in call to CppuType::canBeWarnUnused");
+ }
+}
+
+OUString CppuType::resolveOuterTypedefs(OUString const & name) const
+{
+ for (OUString n(name);;) {
+ rtl::Reference< unoidl::Entity > ent;
+ if (m_typeMgr->getSort(n, &ent) != codemaker::UnoType::Sort::Typedef) {
+ return n;
+ }
+ n = dynamic_cast<unoidl::TypedefEntity&>(*ent).getType();
+ }
+}
+
+OUString CppuType::resolveAllTypedefs(std::u16string_view name) const
+{
+ sal_Int32 k1;
+ OUString n(b2u(codemaker::UnoType::decompose(u2b(name), &k1)));
+ for (;;) {
+ rtl::Reference< unoidl::Entity > ent;
+ if (m_typeMgr->getSort(n, &ent) != codemaker::UnoType::Sort::Typedef) {
+ break;
+ }
+ sal_Int32 k2;
+ n = b2u(codemaker::UnoType::decompose(
+ u2b(dynamic_cast<unoidl::TypedefEntity&>(*ent).getType()), &k2));
+ k1 += k2; //TODO: overflow
+ }
+ OUStringBuffer b(k1*2 + n.getLength());
+ for (sal_Int32 i = 0; i != k1; ++i) {
+ b.append("[]");
+ }
+ b.append(n);
+ return b.makeStringAndClear();
+}
+
+void CppuType::inc(sal_Int32 num)
+{
+ m_indentLength += num;
+}
+
+void CppuType::dec(sal_Int32 num)
+{
+ m_indentLength = std::max< sal_Int32 >(m_indentLength - num, 0);
+}
+
+OUString CppuType::indent() const
+{
+ OUStringBuffer buf(m_indentLength);
+ for (sal_Int32 i = 0; i != m_indentLength; ++i) {
+ buf.append(' ');
+ }
+ return buf.makeStringAndClear();
+}
+
+bool isDeprecated(std::vector< OUString > const & annotations)
+{
+ for (const OUString& r : annotations) {
+ if (r == "deprecated") {
+ return true;
+ }
+ }
+ return false;
+}
+
+void dumpDeprecation(FileStream & out, bool deprecated)
+{
+ if (deprecated) {
+ out << "SAL_DEPRECATED_INTERNAL(\"marked @deprecated in UNOIDL\") ";
+ }
+}
+
+class BaseOffset
+{
+public:
+ BaseOffset(
+ rtl::Reference< TypeManager > manager,
+ rtl::Reference< unoidl::InterfaceTypeEntity > const & entity):
+ manager_(std::move(manager)), offset_(0) {
+ calculateBases(entity);
+ }
+ BaseOffset(const BaseOffset&) = delete;
+ const BaseOffset& operator=(const BaseOffset&) = delete;
+
+ sal_Int32 get() const {
+ return offset_;
+ }
+
+private:
+ void calculateBases(
+ rtl::Reference< unoidl::InterfaceTypeEntity > const & entity);
+
+ rtl::Reference< TypeManager > manager_;
+ std::set< OUString > set_;
+ sal_Int32 offset_;
+};
+
+void BaseOffset::calculateBases(
+ rtl::Reference< unoidl::InterfaceTypeEntity > const & entity)
+{
+ assert(entity.is());
+ for (const unoidl::AnnotatedReference& ar : entity->getDirectMandatoryBases()) {
+ if (set_.insert(ar.name).second) {
+ rtl::Reference< unoidl::Entity > ent;
+ codemaker::UnoType::Sort sort = manager_->getSort(ar.name, &ent);
+ if (sort != codemaker::UnoType::Sort::Interface) {
+ throw CannotDumpException(
+ "interface type base " + ar.name
+ + " is not an interface type");
+ }
+ rtl::Reference< unoidl::InterfaceTypeEntity > ent2(
+ dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get()));
+ assert(ent2.is());
+ calculateBases(ent2);
+ offset_ += ent2->getDirectAttributes().size()
+ + ent2->getDirectMethods().size(); //TODO: overflow
+ }
+ }
+}
+
+class InterfaceType: public CppuType
+{
+public:
+ InterfaceType(
+ rtl::Reference< unoidl::InterfaceTypeEntity > const & entity,
+ OUString const & name, rtl::Reference< TypeManager > const & typeMgr);
+
+ virtual void dumpDeclaration(FileStream& o) override;
+ void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
+
+ void dumpAttributes(FileStream& o) const;
+ void dumpMethods(FileStream& o) const;
+ void dumpNormalGetCppuType(FileStream& o) override;
+ void dumpComprehensiveGetCppuType(FileStream& o) override;
+ void dumpCppuAttributeRefs(FileStream& o, sal_uInt32& index);
+ void dumpCppuMethodRefs(FileStream& o, sal_uInt32& index);
+ void dumpCppuAttributes(FileStream& o, sal_uInt32& index);
+ void dumpCppuMethods(FileStream& o, sal_uInt32& index);
+ void dumpAttributesCppuDecl(FileStream & out, std::set< OUString > * seen) const;
+ void dumpMethodsCppuDecl(FileStream & out, std::set< OUString > * seen) const;
+
+private:
+ virtual void addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const override;
+
+ virtual sal_uInt32 checkInheritedMemberCount() const override {
+ return BaseOffset(m_typeMgr, entity_).get();
+ }
+
+ void dumpExceptionTypeName(
+ FileStream & out, std::u16string_view prefix, sal_uInt32 index,
+ std::u16string_view name) const;
+
+ sal_Int32 dumpExceptionTypeNames(
+ FileStream & out, std::u16string_view prefix,
+ std::vector< OUString > const & exceptions, bool runtimeException) const;
+
+ rtl::Reference< unoidl::InterfaceTypeEntity > entity_;
+ bool m_isDeprecated;
+};
+
+InterfaceType::InterfaceType(
+ rtl::Reference< unoidl::InterfaceTypeEntity > const & entity,
+ OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
+ CppuType(name, typeMgr), entity_(entity),
+ m_isDeprecated(isDeprecated(entity->getAnnotations()))
+{
+ assert(entity.is());
+}
+
+void InterfaceType::dumpDeclaration(FileStream & out)
+{
+ out << "\nclass SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI " << id_;
+ for (std::vector< unoidl::AnnotatedReference >::const_iterator i(
+ entity_->getDirectMandatoryBases().begin());
+ i != entity_->getDirectMandatoryBases().end(); ++i) {
+ out << (i == entity_->getDirectMandatoryBases().begin() ? " :" : ",")
+ << " public " << codemaker::cpp::scopedCppName(u2b(i->name));
+ }
+ out << "\n{\npublic:\n";
+ inc();
+ out << "#if defined LIBO_INTERNAL_ONLY\n"
+ << indent() << id_ << "() = default;\n"
+ << indent() << id_ << "(" << id_ << " const &) = default;\n"
+ << indent() << id_ << "(" << id_ << " &&) = default;\n"
+ << indent() << id_ << " & operator =(" << id_ << " const &) = default;\n"
+ << indent() << id_ << " & operator =(" << id_ << " &&) = default;\n#endif\n\n";
+ dumpAttributes(out);
+ dumpMethods(out);
+ out << "\n" << indent()
+ << ("static inline ::css::uno::Type const & SAL_CALL"
+ " static_type(void * = 0);\n\n");
+ dec();
+ out << "protected:\n";
+ inc();
+ out << indent() << "~" << id_
+ << ("() SAL_NOEXCEPT {} // avoid warnings about virtual members and"
+ " non-virtual dtor\n");
+ dec();
+ out << "};\n\n";
+}
+
+void InterfaceType::dumpHppFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes)
+{
+ OUString headerDefine(dumpHeaderDefine(out, u"HPP"));
+ out << "\n";
+ addDefaultHxxIncludes(includes);
+ includes.dump(out, &name_, !(m_cppuTypeLeak || m_cppuTypeDynamic));
+ out << "\n";
+ dumpGetCppuType(out);
+ out << "\n::css::uno::Type const & "
+ << codemaker::cpp::scopedCppName(u2b(name_))
+ << "::static_type(SAL_UNUSED_PARAMETER void *) {\n";
+ inc();
+ out << indent() << "return ::cppu::UnoType< ";
+ dumpType(out, name_, false, false, true);
+ out << " >::get();\n";
+ dec();
+ out << "}\n\n#endif // "<< headerDefine << "\n";
+}
+
+void InterfaceType::dumpAttributes(FileStream & out) const
+{
+ if (!entity_->getDirectAttributes().empty()) {
+ out << "\n" << indent() << "// Attributes\n";
+ }
+ for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity_->getDirectAttributes()) {
+ bool depr = m_isDeprecated || isDeprecated(attr.annotations);
+ out << indent();
+ dumpDeprecation(out, depr);
+ out << "virtual ";
+ dumpType(out, attr.type);
+ out << " SAL_CALL get" << attr.name << "() = 0;\n";
+ if (!attr.readOnly) {
+ bool byRef = passByReference(attr.type);
+ out << indent();
+ dumpDeprecation(out, depr);
+ out << "virtual void SAL_CALL set" << attr.name << "( ";
+ dumpType(out, attr.type, byRef, byRef);
+ out << " _" << attr.name.toAsciiLowerCase() << " ) = 0;\n";
+ }
+ }
+}
+
+void InterfaceType::dumpMethods(FileStream & out) const
+{
+ if (!entity_->getDirectMethods().empty()) {
+ out << "\n" << indent() << "// Methods\n";
+ }
+ for (const unoidl::InterfaceTypeEntity::Method& method : entity_->getDirectMethods()) {
+ out << indent();
+ dumpDeprecation(out, m_isDeprecated || isDeprecated(method.annotations));
+ out << "virtual ";
+ dumpType(out, method.returnType);
+ out << " SAL_CALL " << method.name << "(";
+ if (!method.parameters.empty()) {
+ out << " ";
+ for (std::vector< unoidl::InterfaceTypeEntity::Method::Parameter >::
+ const_iterator j(method.parameters.begin());
+ j != method.parameters.end();) {
+ bool isConst;
+ bool isRef;
+ if (j->direction
+ == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN)
+ {
+ isConst = passByReference(j->type);
+ isRef = isConst;
+ } else {
+ isConst = false;
+ isRef = true;
+ }
+ dumpType(out, j->type, isConst, isRef);
+ out << " " << j->name;
+ ++j;
+ if (j != method.parameters.end()) {
+ out << ", ";
+ }
+ }
+ out << " ";
+ }
+ out << ") = 0;\n";
+ }
+}
+
+void InterfaceType::dumpNormalGetCppuType(FileStream & out)
+{
+ dumpGetCppuTypePreamble(out);
+ out << indent()
+ << "static typelib_TypeDescriptionReference * the_type = 0;\n"
+ << indent() << "if ( !the_type )\n" << indent() << "{\n";
+ inc();
+ std::vector< unoidl::AnnotatedReference >::size_type bases(
+ entity_->getDirectMandatoryBases().size());
+ if (bases == 1
+ && (entity_->getDirectMandatoryBases()[0].name
+ == "com.sun.star.uno.XInterface")) {
+ bases = 0;
+ }
+ if (bases != 0) {
+ out << indent() << "typelib_TypeDescriptionReference * aSuperTypes["
+ << entity_->getDirectMandatoryBases().size() << "];\n";
+ std::vector< unoidl::AnnotatedReference >::size_type n = 0;
+ for (const unoidl::AnnotatedReference& ar : entity_->getDirectMandatoryBases()) {
+ out << indent() << "aSuperTypes[" << n++ << "] = ::cppu::UnoType< ";
+ dumpType(out, ar.name, true, false, false, true);
+ out << " >::get().getTypeLibType();\n";
+ }
+ }
+ out << indent() << "typelib_static_mi_interface_type_init( &the_type, \""
+ << name_ << "\", " << bases << ", "
+ << (bases == 0 ? "0" : "aSuperTypes") << " );\n";
+ dec();
+ out << indent() << "}\n" << indent()
+ << ("return * reinterpret_cast< ::css::uno::Type * >("
+ " &the_type );\n");
+ dumpGetCppuTypePostamble(out);
+}
+
+void InterfaceType::dumpComprehensiveGetCppuType(FileStream & out)
+{
+ codemaker::cppumaker::dumpNamespaceOpen(out, name_, false);
+ OUString staticTypeClass("the" + id_ + "Type");
+ out << " namespace detail {\n\n" << indent() << "struct " << staticTypeClass
+ << " : public rtl::StaticWithInit< ::css::uno::Type *, "
+ << staticTypeClass << " >\n" << indent() << "{\n";
+ inc();
+ out << indent() << "::css::uno::Type * operator()() const\n"
+ << indent() << "{\n";
+ inc();
+ out << indent() << "::rtl::OUString sTypeName( \"" << name_ << "\" );\n\n"
+ << indent() << "// Start inline typedescription generation\n"
+ << indent() << "typelib_InterfaceTypeDescription * pTD = 0;\n\n";
+ out << indent() << "typelib_TypeDescriptionReference * aSuperTypes["
+ << entity_->getDirectMandatoryBases().size() << "];\n";
+ std::vector< unoidl::AnnotatedReference >::size_type n = 0;
+ for (const unoidl::AnnotatedReference& ar : entity_->getDirectMandatoryBases()) {
+ out << indent() << "aSuperTypes[" << n++ << "] = ::cppu::UnoType< ";
+ dumpType(out, ar.name, false, false, false, true);
+ out << " >::get().getTypeLibType();\n";
+ }
+ std::size_t count = entity_->getDirectAttributes().size()
+ + entity_->getDirectMethods().size(); //TODO: overflow
+ if (count != 0) {
+ out << indent() << "typelib_TypeDescriptionReference * pMembers["
+ << count << "] = { ";
+ for (std::size_t i = 0; i != count; ++i) {
+ out << "0";
+ if (i + 1 != count) {
+ out << ",";
+ }
+ }
+ out << " };\n";
+ sal_uInt32 index = 0;
+ dumpCppuAttributeRefs(out, index);
+ dumpCppuMethodRefs(out, index);
+ }
+ out << "\n" << indent() << "typelib_typedescription_newMIInterface(\n";
+ inc();
+ out << indent() << "&pTD,\n" << indent()
+ << "sTypeName.pData, 0, 0, 0, 0, 0,\n" << indent()
+ << entity_->getDirectMandatoryBases().size() << ", aSuperTypes,\n"
+ << indent() << count << ",\n" << indent()
+ << (count == 0 ? "0" : "pMembers") << " );\n\n";
+ dec();
+ out << indent()
+ << ("typelib_typedescription_register( (typelib_TypeDescription**)&pTD"
+ " );\n");
+ for (std::size_t i = 0; i != count; ++i) {
+ out << indent() << "typelib_typedescriptionreference_release( pMembers["
+ << i << "] );\n";
+ }
+ out << indent()
+ << ("typelib_typedescription_release( (typelib_TypeDescription*)pTD"
+ " );\n\n")
+ << indent() << "return new ::css::uno::Type( "
+ << getTypeClass(name_) << ", sTypeName ); // leaked\n";
+ dec();
+ out << indent() << "}\n";
+ dec();
+ out << indent() << "};\n\n";
+ codemaker::cppumaker::dumpNamespaceClose(out, name_, false);
+ out << " }\n\n";
+ dumpGetCppuTypePreamble(out);
+ out << indent() << "const ::css::uno::Type &rRet = *detail::"
+ << staticTypeClass << "::get();\n" << indent()
+ << "// End inline typedescription generation\n" << indent()
+ << "static bool bInitStarted = false;\n" << indent()
+ << "if (!bInitStarted)\n" << indent() << "{\n";
+ inc();
+ out << indent()
+ << "::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );\n"
+ << indent() << "if (!bInitStarted)\n" << indent() << "{\n";
+ inc();
+ out << indent() << "OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();\n"
+ << indent() << "bInitStarted = true;\n";
+ std::set< OUString > seen;
+ // Type for RuntimeException is always needed:
+ seen.insert("com.sun.star.uno.RuntimeException");
+ dumpCppuGetType(out, u"com.sun.star.uno.RuntimeException");
+ dumpAttributesCppuDecl(out, &seen);
+ dumpMethodsCppuDecl(out, &seen);
+ if (count != 0) {
+ sal_uInt32 index = getInheritedMemberCount();
+ dumpCppuAttributes(out, index);
+ dumpCppuMethods(out, index);
+ }
+ dec();
+ out << indent() << "}\n";
+ dec();
+ out << indent() << "}\n" << indent() << "else\n" << indent() << "{\n";
+ inc();
+ out << indent() << "OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();\n";
+ dec();
+ out << indent() << "}\n" << indent() << "return rRet;\n";
+ dumpGetCppuTypePostamble(out);
+}
+
+void InterfaceType::dumpCppuAttributeRefs(FileStream & out, sal_uInt32 & index)
+{
+ std::vector< unoidl::InterfaceTypeEntity::Attribute >::size_type n = 0;
+ for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity_->getDirectAttributes()) {
+ out << indent() << "::rtl::OUString sAttributeName" << n << "( \""
+ << name_ << "::" << attr.name << "\" );\n" << indent()
+ << "typelib_typedescriptionreference_new( &pMembers[" << index++
+ << "],\n";
+ inc(38);
+ out << indent()
+ << "(typelib_TypeClass)::css::uno::TypeClass_INTERFACE_ATTRIBUTE,\n"
+ << indent() << "sAttributeName" << n << ".pData );\n";
+ dec(38);
+ ++n;
+ }
+}
+
+void InterfaceType::dumpCppuMethodRefs(FileStream & out, sal_uInt32 & index)
+{
+ std::vector< unoidl::InterfaceTypeEntity::Method >::size_type n = 0;
+ for (const unoidl::InterfaceTypeEntity::Method& method : entity_->getDirectMethods()) {
+ out << indent() << "::rtl::OUString sMethodName" << n << "( \"" << name_
+ << "::" << method.name << "\" );\n" << indent()
+ << "typelib_typedescriptionreference_new( &pMembers[" << index++
+ << "],\n";
+ inc(38);
+ out << indent()
+ << "(typelib_TypeClass)::css::uno::TypeClass_INTERFACE_METHOD,\n"
+ << indent() << "sMethodName" << n << ".pData );\n";
+ dec(38);
+ ++n;
+ }
+}
+
+void InterfaceType::addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ // The comprehensive getCppuType method always includes a line
+ // "getCppuType( (const ::css::uno::RuntimeException*)0 );":
+ includes.addCppuUnotypeHxx();
+ includes.addRtlInstanceHxx(); // using rtl::StaticWithInit
+ includes.addOslMutexHxx();
+ includes.add("com.sun.star.uno.RuntimeException");
+}
+
+void InterfaceType::dumpCppuAttributes(FileStream & out, sal_uInt32 & index)
+{
+ if (entity_->getDirectAttributes().empty())
+ return;
+
+ out << "\n" << indent()
+ << "typelib_InterfaceAttributeTypeDescription * pAttribute = 0;\n";
+ std::vector< unoidl::InterfaceTypeEntity::Attribute >::size_type n = 0;
+ for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity_->getDirectAttributes()) {
+ OUString type(resolveAllTypedefs(attr.type));
+ out << indent() << "{\n";
+ inc();
+ out << indent() << "::rtl::OUString sAttributeType" << n << "( \""
+ << type << "\" );\n" << indent()
+ << "::rtl::OUString sAttributeName" << n << "( \"" << name_
+ << "::" << attr.name << "\" );\n";
+ sal_Int32 getExcn = dumpExceptionTypeNames(
+ out, u"get", attr.getExceptions, false);
+ sal_Int32 setExcn = dumpExceptionTypeNames(
+ out, u"set", attr.setExceptions, false);
+ out << indent()
+ << ("typelib_typedescription_newExtendedInterfaceAttribute("
+ " &pAttribute,\n");
+ inc();
+ out << indent() << index++ << ", sAttributeName" << n
+ << ".pData,\n" << indent() << "(typelib_TypeClass)"
+ << getTypeClass(type) << ", sAttributeType" << n << ".pData,\n"
+ << indent() << "sal_" << (attr.readOnly ? "True" : "False")
+ << ", " << getExcn << ", "
+ << (getExcn == 0 ? "0" : "the_getExceptions") << ", " << setExcn
+ << ", " << (setExcn == 0 ? "0" : "the_setExceptions")
+ << " );\n";
+ dec();
+ out << indent()
+ << ("typelib_typedescription_register("
+ " (typelib_TypeDescription**)&pAttribute );\n");
+ dec();
+ out << indent() << "}\n";
+ ++n;
+ }
+ out << indent()
+ << ("typelib_typedescription_release("
+ " (typelib_TypeDescription*)pAttribute );\n");
+}
+
+void InterfaceType::dumpCppuMethods(FileStream & out, sal_uInt32 & index)
+{
+ if (entity_->getDirectMethods().empty())
+ return;
+
+ out << "\n" << indent()
+ << "typelib_InterfaceMethodTypeDescription * pMethod = 0;\n";
+ std::vector< unoidl::InterfaceTypeEntity::Method >::size_type n = 0;
+ for (const unoidl::InterfaceTypeEntity::Method& method : entity_->getDirectMethods()) {
+ OUString returnType(resolveAllTypedefs(method.returnType));
+ out << indent() << "{\n";
+ inc();
+ if (!method.parameters.empty()) {
+ out << indent() << "typelib_Parameter_Init aParameters["
+ << method.parameters.size() << "];\n";
+ }
+ std::vector< unoidl::InterfaceTypeEntity::Method::Parameter >::
+ size_type m = 0;
+ for (const unoidl::InterfaceTypeEntity::Method::Parameter& param : method.parameters) {
+ OUString type(resolveAllTypedefs(param.type));
+ out << indent() << "::rtl::OUString sParamName" << m << "( \""
+ << param.name << "\" );\n" << indent()
+ << "::rtl::OUString sParamType" << m << "( \"" << type
+ << "\" );\n" << indent() << "aParameters[" << m
+ << "].pParamName = sParamName" << m << ".pData;\n"
+ << indent() << "aParameters[" << m
+ << "].eTypeClass = (typelib_TypeClass)"
+ << getTypeClass(type) << ";\n" << indent() << "aParameters["
+ << m << "].pTypeName = sParamType" << m << ".pData;\n"
+ << indent() << "aParameters[" << m << "].bIn = "
+ << ((param.direction
+ == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT)
+ ? "sal_False" : "sal_True")
+ << ";\n" << indent() << "aParameters[" << m << "].bOut = "
+ << ((param.direction
+ == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN)
+ ? "sal_False" : "sal_True")
+ << ";\n";
+ ++m;
+ }
+ sal_Int32 excn = dumpExceptionTypeNames(
+ out, u"", method.exceptions,
+ method.name != "acquire" && method.name != "release");
+ out << indent() << "::rtl::OUString sReturnType" << n << "( \""
+ << returnType << "\" );\n" << indent()
+ << "::rtl::OUString sMethodName" << n << "( \"" << name_ << "::"
+ << method.name << "\" );\n" << indent()
+ << "typelib_typedescription_newInterfaceMethod( &pMethod,\n";
+ inc();
+ out << indent() << index++ << ", sal_False,\n" << indent()
+ << "sMethodName" << n << ".pData,\n" << indent()
+ << "(typelib_TypeClass)" << getTypeClass(returnType)
+ << ", sReturnType" << n << ".pData,\n" << indent()
+ << method.parameters.size() << ", "
+ << (method.parameters.empty() ? "0" : "aParameters") << ",\n"
+ << indent() << excn << ", "
+ << (excn == 0 ? "0" : "the_Exceptions") << " );\n";
+ dec();
+ out << indent()
+ << ("typelib_typedescription_register("
+ " (typelib_TypeDescription**)&pMethod );\n");
+ dec();
+ out << indent() << "}\n";
+ ++n;
+ }
+ out << indent()
+ << ("typelib_typedescription_release("
+ " (typelib_TypeDescription*)pMethod );\n");
+}
+
+void InterfaceType::dumpAttributesCppuDecl(
+ FileStream & out, std::set< OUString > * seen) const
+{
+ assert(seen != nullptr);
+ for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity_->getDirectAttributes()) {
+ if (seen->insert(attr.type).second) {
+ dumpCppuGetType(out, attr.type);
+ }
+ for (const OUString& exc : attr.getExceptions) {
+ if (seen->insert(exc).second) {
+ dumpCppuGetType(out, exc);
+ }
+ }
+ for (const OUString& exc : attr.setExceptions) {
+ if (seen->insert(exc).second) {
+ dumpCppuGetType(out, exc);
+ }
+ }
+ }
+}
+
+void InterfaceType::dumpMethodsCppuDecl(
+ FileStream & out, std::set< OUString > * seen) const
+{
+ assert(seen != nullptr);
+ for (const unoidl::InterfaceTypeEntity::Method& method : entity_->getDirectMethods()) {
+ for (const OUString& ex : method.exceptions) {
+ if (seen->insert(ex).second) {
+ dumpCppuGetType(out, ex);
+ }
+ }
+ }
+}
+
+void InterfaceType::dumpExceptionTypeName(
+ FileStream & out, std::u16string_view prefix, sal_uInt32 index,
+ std::u16string_view name) const
+{
+ out << indent() << "::rtl::OUString the_" << prefix << "ExceptionName"
+ << index << "( \"" << name << "\" );\n";
+}
+
+sal_Int32 InterfaceType::dumpExceptionTypeNames(
+ FileStream & out, std::u16string_view prefix,
+ std::vector< OUString > const & exceptions, bool runtimeException) const
+{
+ sal_Int32 count = 0;
+ for (const OUString& ex : exceptions) {
+ if (ex != "com.sun.star.uno.RuntimeException") {
+ dumpExceptionTypeName(out, prefix, count++, ex);
+ }
+ }
+ if (runtimeException) {
+ dumpExceptionTypeName(
+ out, prefix, count++, u"com.sun.star.uno.RuntimeException");
+ }
+ if (count != 0) {
+ out << indent() << "rtl_uString * the_" << prefix << "Exceptions[] = {";
+ for (sal_Int32 i = 0; i != count; ++i) {
+ out << (i == 0 ? " " : ", ") << "the_" << prefix << "ExceptionName"
+ << i << ".pData";
+ }
+ out << " };\n";
+ }
+ return count;
+}
+
+class ConstantGroup: public CppuType
+{
+public:
+ ConstantGroup(
+ rtl::Reference< unoidl::ConstantGroupEntity > const & entity,
+ OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
+ CppuType(name, typeMgr), entity_(entity) {
+ assert(entity.is());
+ }
+
+ bool hasConstants() const {
+ return !entity_->getMembers().empty();
+ }
+
+private:
+ virtual void dumpHdlFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes) override;
+
+ virtual void dumpHppFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes) override;
+
+ virtual void dumpDeclaration(FileStream & out) override;
+
+ rtl::Reference< unoidl::ConstantGroupEntity > entity_;
+};
+
+void ConstantGroup::dumpHdlFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes)
+{
+ OUString headerDefine(dumpHeaderDefine(out, u"HDL"));
+ out << "\n";
+ addDefaultHIncludes(includes);
+ includes.dump(out, nullptr, true);
+ out << "\n";
+ if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, true)) {
+ out << "\n";
+ }
+ out << "\n";
+ dumpDeclaration(out);
+ out << "\n";
+ if (codemaker::cppumaker::dumpNamespaceClose(out, name_, true)) {
+ out << "\n";
+ }
+ out << "\n#endif // "<< headerDefine << "\n";
+}
+
+void ConstantGroup::dumpHppFile(
+ FileStream & out, codemaker::cppumaker::Includes &)
+{
+ OUString headerDefine(dumpHeaderDefine(out, u"HPP"));
+ out << "\n";
+ codemaker::cppumaker::Includes::dumpInclude(out, u2b(name_), false);
+ out << "\n#endif // "<< headerDefine << "\n";
+}
+
+void ConstantGroup::dumpDeclaration(FileStream & out)
+{
+ for (const unoidl::ConstantGroupEntity::Member& member : entity_->getMembers()) {
+ out << "static const ";
+ switch (member.value.type) {
+ case unoidl::ConstantValue::TYPE_BOOLEAN:
+ out << "::sal_Bool";
+ break;
+ case unoidl::ConstantValue::TYPE_BYTE:
+ out << "::sal_Int8";
+ break;
+ case unoidl::ConstantValue::TYPE_SHORT:
+ out << "::sal_Int16";
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
+ out << "::sal_uInt16";
+ break;
+ case unoidl::ConstantValue::TYPE_LONG:
+ out << "::sal_Int32";
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
+ out << "::sal_uInt32";
+ break;
+ case unoidl::ConstantValue::TYPE_HYPER:
+ out << "::sal_Int64";
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
+ out << "::sal_uInt64";
+ break;
+ case unoidl::ConstantValue::TYPE_FLOAT:
+ out << "float";
+ break;
+ case unoidl::ConstantValue::TYPE_DOUBLE:
+ out << "double";
+ break;
+ }
+ out << " " << member.name << " = ";
+ switch (member.value.type) {
+ case unoidl::ConstantValue::TYPE_BOOLEAN:
+ out << (member.value.booleanValue ? "sal_True" : "sal_False");
+ break;
+ case unoidl::ConstantValue::TYPE_BYTE:
+ out << "(sal_Int8)" << OUString::number(member.value.byteValue);
+ break;
+ case unoidl::ConstantValue::TYPE_SHORT:
+ out << "(sal_Int16)" << OUString::number(member.value.shortValue);
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
+ out << "(sal_uInt16)"
+ << OUString::number(member.value.unsignedShortValue);
+ break;
+ case unoidl::ConstantValue::TYPE_LONG:
+ // Avoid C++ compiler warnings about (un)signedness of literal
+ // -2^31:
+ if (member.value.longValue == SAL_MIN_INT32) {
+ out << "SAL_MIN_INT32";
+ } else {
+ out << "(sal_Int32)" << OUString::number(member.value.longValue);
+ }
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
+ out << "(sal_uInt32)"
+ << OUString::number(member.value.unsignedLongValue) << "U";
+ break;
+ case unoidl::ConstantValue::TYPE_HYPER:
+ // Avoid C++ compiler warnings about (un)signedness of literal
+ // -2^63:
+ if (member.value.hyperValue == SAL_MIN_INT64) {
+ out << "SAL_MIN_INT64";
+ } else {
+ out << "(sal_Int64) SAL_CONST_INT64("
+ << OUString::number(member.value.hyperValue) << ")";
+ }
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
+ out << "SAL_CONST_UINT64("
+ << OUString::number(member.value.unsignedHyperValue) << ")";
+ break;
+ case unoidl::ConstantValue::TYPE_FLOAT:
+ out << "(float)" << OUString::number(member.value.floatValue);
+ break;
+ case unoidl::ConstantValue::TYPE_DOUBLE:
+ out << "(double)" << OUString::number(member.value.doubleValue);
+ break;
+ }
+ out << ";\n";
+ }
+}
+
+void dumpTypeParameterName(FileStream & out, std::u16string_view name)
+{
+ // Prefix all type parameters with "typeparam_" to avoid problems when a
+ // struct member has the same name as a type parameter, as in
+ // struct<T> { T T; };
+ out << "typeparam_" << name;
+}
+
+class PlainStructType: public CppuType
+{
+public:
+ PlainStructType(
+ rtl::Reference< unoidl::PlainStructTypeEntity > const & entity,
+ OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
+ CppuType(name, typeMgr), entity_(entity) {
+ assert(entity.is());
+ }
+
+private:
+ virtual sal_uInt32 checkInheritedMemberCount() const override {
+ return getTotalMemberCount(entity_->getDirectBase());
+ }
+
+ virtual void dumpDeclaration(FileStream& o) override;
+
+ void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
+
+ virtual void dumpLightGetCppuType(FileStream & out) override;
+
+ virtual void dumpNormalGetCppuType(FileStream & out) override;
+
+ virtual void dumpComprehensiveGetCppuType(FileStream & out) override;
+
+ virtual void addLightGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const override;
+
+ virtual void addNormalGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const override;
+
+ virtual void addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const override;
+
+ bool dumpBaseMembers(
+ FileStream & out, OUString const & base, bool withType);
+
+ sal_uInt32 getTotalMemberCount(OUString const & base) const;
+
+ rtl::Reference< unoidl::PlainStructTypeEntity > entity_;
+};
+
+void PlainStructType::dumpDeclaration(FileStream & out)
+{
+ out << "\n#ifdef _WIN32\n# pragma pack(push, 8)\n#endif\n\n" << indent();
+ out << "struct SAL_DLLPUBLIC_RTTI ";
+ if (canBeWarnUnused(name_))
+ out << "SAL_WARN_UNUSED ";
+ out << id_;
+ OUString base(entity_->getDirectBase());
+ if (!base.isEmpty()) {
+ out << ": public " << codemaker::cpp::scopedCppName(u2b(base));
+ }
+ out << " {\n";
+ inc();
+ out << indent() << "inline " << id_ << "();\n";
+ if (!entity_->getDirectMembers().empty() || getInheritedMemberCount() > 0) {
+ out << "\n" << indent() << "inline " << id_ << "(";
+ bool bFirst = !dumpBaseMembers(out, base, true);
+ for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) {
+ if (!bFirst) {
+ out << ", ";
+ }
+ dumpType(out, member.type, true, true);
+ out << " " << member.name << "_";
+ bFirst = false;
+ }
+ out << ");\n";
+ }
+ if (!entity_->getDirectMembers().empty()) {
+ out << "\n";
+ for (std::vector< unoidl::PlainStructTypeEntity::Member >::
+ const_iterator i(entity_->getDirectMembers().begin());
+ i != entity_->getDirectMembers().end(); ++i) {
+ out << indent();
+ dumpType(out, i->type);
+ out << " " << i->name;
+ if (i == entity_->getDirectMembers().begin() && !base.isEmpty()
+ && i->type != "hyper" && i->type != "unsigned hyper"
+ && i->type != "double") {
+ out << " CPPU_GCC3_ALIGN("
+ << codemaker::cpp::scopedCppName(u2b(base)) << ")";
+ }
+ out << ";\n";
+ }
+ }
+ dec();
+ out << "};\n\n#ifdef _WIN32\n# pragma pack(pop)\n#endif\n\n";
+}
+
+void PlainStructType::dumpHppFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes)
+{
+ OUString headerDefine(dumpHeaderDefine(out, u"HPP"));
+ out << "\n";
+ includes.dump(out, &name_, true);
+ out << "\n";
+ if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) {
+ out << "\n";
+ }
+ out << "\ninline " << id_ << "::" << id_ << "()\n";
+ inc();
+ OUString base(entity_->getDirectBase());
+ bool bFirst = true;
+ if (!base.isEmpty()) {
+ out << indent() << ": " << codemaker::cpp::scopedCppName(u2b(base))
+ << "()\n";
+ bFirst = false;
+ }
+ for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) {
+ out << indent() << (bFirst ? ":" : ",") << " " << member.name;
+ dumpInitializer(out, false, member.type);
+ out << "\n";
+ bFirst = false;
+ }
+ dec();
+ out << "{\n}\n\n";
+ if (!entity_->getDirectMembers().empty() || getInheritedMemberCount() > 0) {
+ out << "inline " << id_;
+ out << "::" << id_ << "(";
+ bFirst = !dumpBaseMembers(out, base, true);
+ for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) {
+ if (!bFirst) {
+ out << ", ";
+ }
+ dumpType(out, member.type, true, true);
+ out << " " << member.name << "_";
+ bFirst = false;
+ }
+ out << ")\n";
+ inc();
+ bFirst = true;
+ if (!base.isEmpty()) {
+ out << indent() << ": " << codemaker::cpp::scopedCppName(u2b(base))
+ << "(";
+ dumpBaseMembers(out, base, false);
+ out << ")\n";
+ bFirst = false;
+ }
+ for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) {
+ out << indent() << (bFirst ? ":" : ",") << " " << member.name << "("
+ << member.name << "_)\n";
+ bFirst = false;
+ }
+ dec();
+ out << "{\n}\n\n";
+ }
+ // print the operator==
+ out << "\ninline bool operator==(const " << id_ << "& the_lhs, const " << id_ << "& the_rhs)\n";
+ out << "{\n";
+ inc();
+ out << indent() << "return ";
+ bFirst = true;
+ if (!base.isEmpty()) {
+ out << "operator==( static_cast< " << codemaker::cpp::scopedCppName(u2b(base))
+ << ">(the_lhs), static_cast< " << codemaker::cpp::scopedCppName(u2b(base)) << ">(the_rhs) )\n";
+ bFirst = false;
+ }
+ for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) {
+ if (!bFirst)
+ out << "\n" << indent() << indent() << "&& ";
+ out << "the_lhs." << member.name << " == the_rhs." << member.name;
+ bFirst = false;
+ }
+ out << ";\n";
+ dec();
+ out << "}\n";
+ // print the operator!=
+ out << "\ninline bool operator!=(const " << id_ << "& the_lhs, const " << id_ << "& the_rhs)\n";
+ out << "{\n";
+ out << indent() << "return !operator==(the_lhs, the_rhs);\n";
+ out << "}\n";
+ // close namespace
+ if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) {
+ out << "\n";
+ }
+ out << "\n";
+ dumpGetCppuType(out);
+ out << "\n#endif // "<< headerDefine << "\n";
+}
+
+void PlainStructType::dumpLightGetCppuType(FileStream & out)
+{
+ dumpGetCppuTypePreamble(out);
+ out << indent()
+ << ("//TODO: On certain platforms with weak memory models, the"
+ " following code can result in some threads observing that the_type"
+ " points to garbage\n")
+ << indent()
+ << "static ::typelib_TypeDescriptionReference * the_type = 0;\n"
+ << indent() << "if (the_type == 0) {\n";
+ inc();
+ out << indent() << "::typelib_static_type_init(&the_type, "
+ << getTypeClass(name_, true) << ", \"" << name_ << "\");\n";
+ dec();
+ out << indent() << "}\n" << indent()
+ << "return *reinterpret_cast< ::css::uno::Type * >(&the_type);\n";
+ dumpGetCppuTypePostamble(out);
+}
+
+void PlainStructType::dumpNormalGetCppuType(FileStream & out)
+{
+ dumpGetCppuTypePreamble(out);
+ out << indent()
+ << ("//TODO: On certain platforms with weak memory models, the"
+ " following code can result in some threads observing that the_type"
+ " points to garbage\n")
+ << indent()
+ << "static ::typelib_TypeDescriptionReference * the_type = 0;\n"
+ << indent() << "if (the_type == 0) {\n";
+ inc();
+ out << indent()
+ << "::typelib_TypeDescriptionReference * the_members[] = {\n";
+ inc();
+ for (std::vector< unoidl::PlainStructTypeEntity::Member >::const_iterator i(
+ entity_->getDirectMembers().begin());
+ i != entity_->getDirectMembers().end();) {
+ out << indent() << "::cppu::UnoType< ";
+ dumpType(out, i->type, false, false, false, true);
+ ++i;
+ out << " >::get().getTypeLibType()"
+ << (i == entity_->getDirectMembers().end() ? " };" : ",") << "\n";
+ }
+ dec();
+ out << indent() << "::typelib_static_struct_type_init(&the_type, \""
+ << name_ << "\", ";
+ if (entity_->getDirectBase().isEmpty()) {
+ out << "0";
+ } else {
+ out << "::cppu::UnoType< ";
+ dumpType(out, entity_->getDirectBase(), false, false, false, true);
+ out << " >::get().getTypeLibType()";
+ }
+ out << ", " << entity_->getDirectMembers().size() << ", the_members, 0);\n";
+ dec();
+ out << indent() << "}\n" << indent()
+ << "return *reinterpret_cast< ::css::uno::Type * >(&the_type);\n";
+ dumpGetCppuTypePostamble(out);
+}
+
+void PlainStructType::dumpComprehensiveGetCppuType(FileStream & out)
+{
+ OUString staticTypeClass("the" + id_ + "Type");
+ codemaker::cppumaker::dumpNamespaceOpen(out, name_, false);
+ out << " namespace detail {\n\n" << indent() << "struct "
+ << staticTypeClass
+ << " : public rtl::StaticWithInit< ::css::uno::Type *, "
+ << staticTypeClass << " >\n" << indent() << "{\n";
+ inc();
+ out << indent() << "::css::uno::Type * operator()() const\n"
+ << indent() << "{\n";
+ inc();
+ out << indent() << "::rtl::OUString the_name( \"" << name_ << "\" );\n";
+ std::map< OUString, sal_uInt32 > types;
+ std::vector< unoidl::PlainStructTypeEntity::Member >::size_type n = 0;
+ for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) {
+ if (types.emplace(
+ member.type, static_cast< sal_uInt32 >(types.size())).
+ second) {
+ dumpCppuGetType(out, member.type, &name_);
+ // For typedefs, use the resolved type name, as there will be no
+ // information available about the typedef itself at runtime (the
+ // above getCppuType call will make available information about the
+ // resolved type); no extra #include for the resolved type is
+ // needed, as the header for the typedef includes it already:
+ out << indent() << "::rtl::OUString the_tname"
+ << static_cast< sal_uInt32 >(types.size() - 1) << "( \""
+ << resolveAllTypedefs(member.type) << "\" );\n";
+ }
+ out << indent() << "::rtl::OUString the_name" << n++ << "( \""
+ << member.name << "\" );\n";
+ }
+ out << indent() << "::typelib_StructMember_Init the_members[] = {\n";
+ inc();
+ n = 0;
+ for (std::vector< unoidl::PlainStructTypeEntity::Member >::const_iterator i(
+ entity_->getDirectMembers().begin());
+ i != entity_->getDirectMembers().end();) {
+ out << indent() << "{ { " << getTypeClass(i->type, true)
+ << ", the_tname" << types.find(i->type)->second
+ << ".pData, the_name" << n++ << ".pData }, false }";
+ ++i;
+ out << (i == entity_->getDirectMembers().end() ? " };" : ",") << "\n";
+ }
+ dec();
+ out << indent() << "::typelib_TypeDescription * the_newType = 0;\n"
+ << indent()
+ << "::typelib_typedescription_newStruct(&the_newType, the_name.pData, ";
+ if (entity_->getDirectBase().isEmpty()) {
+ out << "0";
+ } else {
+ out << "::cppu::UnoType< ";
+ dumpType(out, entity_->getDirectBase(), false, false, false, true);
+ out << " >::get().getTypeLibType()";
+ }
+ out << ", " << entity_->getDirectMembers().size() << ", the_members);\n"
+ << indent() << "::typelib_typedescription_register(&the_newType);\n"
+ << indent() << "::typelib_typedescription_release(the_newType);\n"
+ << indent() << "return new ::css::uno::Type("
+ << getTypeClass(name_) << ", the_name); // leaked\n";
+ dec();
+ out << indent() << "}\n";
+ dec();
+ out << indent() << "};\n";
+ codemaker::cppumaker::dumpNamespaceClose(out, name_, false);
+ out << " }\n\n";
+ dumpGetCppuTypePreamble(out);
+ out << indent() << "return *detail::" << staticTypeClass << "::get();\n";
+ dumpGetCppuTypePostamble(out);
+}
+
+bool PlainStructType::dumpBaseMembers(
+ FileStream & out, OUString const & base, bool withType)
+{
+ if (base.isEmpty())
+ return false;
+
+ rtl::Reference< unoidl::Entity > ent;
+ codemaker::UnoType::Sort sort = m_typeMgr->getSort(base, &ent);
+ if (sort != codemaker::UnoType::Sort::PlainStruct) {
+ throw CannotDumpException(
+ "plain struct type base " + base
+ + " is not a plain struct type");
+ }
+ rtl::Reference< unoidl::PlainStructTypeEntity > ent2(
+ dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get()));
+ assert(ent2.is());
+ if (!ent2.is()) {
+ return false;
+ }
+ bool hasMember = dumpBaseMembers(out, ent2->getDirectBase(), withType);
+ for (const unoidl::PlainStructTypeEntity::Member& member : ent2->getDirectMembers()) {
+ if (hasMember) {
+ out << ", ";
+ }
+ if (withType) {
+ dumpType(out, member.type, true, true);
+ out << " ";
+ }
+ out << member.name << "_";
+ hasMember = true;
+ }
+ return hasMember;
+}
+
+void PlainStructType::addLightGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ includes.addType();
+ includes.addCppuUnotypeHxx();
+ includes.addSalTypesH();
+ includes.addTypelibTypeclassH();
+ includes.addTypelibTypedescriptionH();
+}
+
+void PlainStructType::addNormalGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ includes.addType();
+ includes.addCppuUnotypeHxx();
+ includes.addSalTypesH();
+ includes.addTypelibTypeclassH();
+ includes.addTypelibTypedescriptionH();
+}
+
+void PlainStructType::addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ includes.addType();
+ includes.addCppuUnotypeHxx();
+ includes.addRtlInstanceHxx();
+ includes.addRtlUstringH();
+ includes.addRtlUstringHxx();
+ includes.addSalTypesH();
+ includes.addTypelibTypeclassH();
+ includes.addTypelibTypedescriptionH();
+}
+
+sal_uInt32 PlainStructType::getTotalMemberCount(OUString const & base) const
+{
+ if (base.isEmpty()) {
+ return 0;
+ }
+ rtl::Reference< unoidl::Entity > ent;
+ codemaker::UnoType::Sort sort = m_typeMgr->getSort(base, &ent);
+ if (sort != codemaker::UnoType::Sort::PlainStruct) {
+ throw CannotDumpException(
+ "plain struct type base " + base + " is not a plain struct type");
+ }
+ rtl::Reference< unoidl::PlainStructTypeEntity > ent2(
+ dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get()));
+ assert(ent2.is());
+ if (!ent2.is()) {
+ return 0;
+ }
+ return getTotalMemberCount(ent2->getDirectBase())
+ + ent2->getDirectMembers().size(); //TODO: overflow
+}
+
+class PolyStructType: public CppuType
+{
+public:
+ PolyStructType(
+ rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > const &
+ entity,
+ OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
+ CppuType(name, typeMgr), entity_(entity) {
+ assert(entity.is());
+ }
+
+private:
+ virtual void dumpDeclaration(FileStream& o) override;
+
+ void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
+
+ virtual void dumpLightGetCppuType(FileStream & out) override;
+
+ virtual void dumpNormalGetCppuType(FileStream & out) override;
+
+ virtual void dumpComprehensiveGetCppuType(FileStream & out) override;
+
+ virtual void addLightGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const override;
+
+ virtual void addNormalGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const override;
+
+ virtual void addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const override;
+
+ virtual bool isPolymorphic() const override {
+ return true;
+ }
+
+ virtual void dumpTemplateHead(FileStream & out) const override;
+
+ virtual void dumpTemplateParameters(FileStream & out) const override;
+
+ rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > entity_;
+};
+
+void PolyStructType::dumpDeclaration(FileStream & out)
+{
+ out << "\n#ifdef _WIN32\n# pragma pack(push, 8)\n#endif\n\n" << indent();
+ dumpTemplateHead(out);
+ out << "struct SAL_DLLPUBLIC_RTTI " << id_ << " {\n";
+ inc();
+ out << indent() << "inline " << id_ << "();\n";
+ if (!entity_->getMembers().empty()) {
+ out << "\n" << indent() << "inline " << id_ << "(";
+ for (std::vector<
+ unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ const_iterator i(entity_->getMembers().begin());
+ i != entity_->getMembers().end(); ++i) {
+ if (i != entity_->getMembers().begin()) {
+ out << ", ";
+ }
+ if (i->parameterized) {
+ dumpTypeParameterName(out, i->type);
+ out << " const &";
+ } else {
+ dumpType(out, i->type, true, true);
+ }
+ out << " " << i->name << "_";
+ }
+ out << ");\n\n";
+ // print the member fields
+ for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member :
+ entity_->getMembers()) {
+ out << indent();
+ if (member.parameterized) {
+ dumpTypeParameterName(out, member.type);
+ } else {
+ dumpType(out, member.type);
+ }
+ out << " " << member.name << ";\n";
+ }
+ }
+ dec();
+ out << "};\n\n#ifdef _WIN32\n# pragma pack(pop)\n#endif\n\n";
+}
+
+void PolyStructType::dumpHppFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes)
+{
+ OUString headerDefine(dumpHeaderDefine(out, u"HPP"));
+ out << "\n";
+ includes.dump(out, &name_, true);
+ out << "\n";
+ if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) {
+ out << "\n";
+ }
+ out << "\n";
+ // dump default (no-arg) constructor
+ dumpTemplateHead(out);
+ out << "inline " << id_;
+ dumpTemplateParameters(out);
+ out << "::" << id_ << "()\n";
+ inc();
+ for (std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ const_iterator i(entity_->getMembers().begin());
+ i != entity_->getMembers().end(); ++i) {
+ out << indent() << (i == entity_->getMembers().begin() ? ":" : ",")
+ << " " << i->name;
+ dumpInitializer(out, i->parameterized, i->type);
+ out << "\n";
+ }
+ dec();
+ out << "{\n}\n\n";
+ if (!entity_->getMembers().empty()) {
+ // dump takes-all-fields constructor
+ dumpTemplateHead(out);
+ out << "inline " << id_;
+ dumpTemplateParameters(out);
+ out << "::" << id_ << "(";
+ for (std::vector<
+ unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ const_iterator i(entity_->getMembers().begin());
+ i != entity_->getMembers().end(); ++i) {
+ if (i != entity_->getMembers().begin()) {
+ out << ", ";
+ }
+ if (i->parameterized) {
+ dumpTypeParameterName(out, i->type);
+ out << " const &";
+ } else {
+ dumpType(out, i->type, true, true);
+ }
+ out << " " << i->name << "_";
+ }
+ out << ")\n";
+ inc();
+ for (std::vector<
+ unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ const_iterator i(entity_->getMembers().begin());
+ i != entity_->getMembers().end(); ++i) {
+ out << indent() << (i == entity_->getMembers().begin() ? ":" : ",")
+ << " " << i->name << "(" << i->name << "_)\n";
+ }
+ dec();
+ out << "{\n}\n\n" << indent();
+ // dump make_T method
+ dumpTemplateHead(out);
+ out << "\n" << indent() << "inline " << id_;
+ dumpTemplateParameters(out);
+ out << "\n" << indent() << "make_" << id_ << "(";
+ for (std::vector<
+ unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ const_iterator i(entity_->getMembers().begin());
+ i != entity_->getMembers().end(); ++i) {
+ if (i != entity_->getMembers().begin()) {
+ out << ", ";
+ }
+ if (i->parameterized) {
+ dumpTypeParameterName(out, i->type);
+ out << " const &";
+ } else {
+ dumpType(out, i->type, true, true);
+ }
+ out << " " << i->name << "_";
+ }
+ out << ")\n" << indent() << "{\n";
+ inc();
+ out << indent() << "return " << id_;
+ dumpTemplateParameters(out);
+ out << "(";
+ for (std::vector<
+ unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ const_iterator i(entity_->getMembers().begin());
+ i != entity_->getMembers().end(); ++i) {
+ if (i != entity_->getMembers().begin()) {
+ out << ", ";
+ }
+ out << i->name << "_";
+ }
+ out << ");\n";
+ dec();
+ out << indent() << "}\n\n";
+ }
+ // print the operator==
+ dumpTemplateHead(out);
+ out << " inline bool operator==(const " << id_;
+ dumpTemplateParameters(out);
+ out << "& the_lhs, const " << id_;
+ dumpTemplateParameters(out);
+ out << "& the_rhs)\n";
+ out << "{\n";
+ inc();
+ out << indent() << "return ";
+ bool bFirst = true;
+ for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity_->getMembers()) {
+ if (!bFirst)
+ out << "\n" << indent() << indent() << "&& ";
+ out << "the_lhs." << member.name << " == the_rhs." << member.name;
+ bFirst = false;
+ }
+ out << ";\n";
+ dec();
+ out << "}\n";
+ // print the operator!=
+ dumpTemplateHead(out);
+ out << " inline bool operator!=(const " << id_;
+ dumpTemplateParameters(out);
+ out << "& the_lhs, const " << id_;
+ dumpTemplateParameters(out);
+ out << "& the_rhs)\n";
+ out << "{\n";
+ out << indent() << "return !operator==(the_lhs, the_rhs);\n";
+ out << "}\n";
+ // close namespace
+ if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) {
+ out << "\n";
+ }
+ out << "\n";
+ dumpGetCppuType(out);
+ out << "\n#endif // "<< headerDefine << "\n";
+}
+
+void PolyStructType::dumpLightGetCppuType(FileStream & out)
+{
+ dumpGetCppuTypePreamble(out);
+ out << indent()
+ << ("//TODO: On certain platforms with weak memory models, the"
+ " following code can result in some threads observing that the_type"
+ " points to garbage\n")
+ << indent()
+ << "static ::typelib_TypeDescriptionReference * the_type = 0;\n"
+ << indent() << "if (the_type == 0) {\n";
+ inc();
+
+ out << "#ifdef LIBO_INTERNAL_ONLY\n";
+
+ out << indent() << "::rtl::OString the_buffer = \"" << name_
+ << "<\" +\n";
+ for (std::vector< OUString >::const_iterator i(
+ entity_->getTypeParameters().begin());
+ i != entity_->getTypeParameters().end();) {
+ out << indent()
+ << ("::rtl::OUStringToOString("
+ "::cppu::getTypeFavourChar(static_cast< ");
+ dumpTypeParameterName(out, *i);
+ out << " * >(0)).getTypeName(), RTL_TEXTENCODING_UTF8) +\n";
+ ++i;
+ if (i != entity_->getTypeParameters().end()) {
+ out << indent() << "\",\" +\n";
+ }
+ }
+ out << indent() << "\">\";\n";
+
+ out << "#else\n";
+
+ out << indent() << "::rtl::OStringBuffer the_buffer(\"" << name_
+ << "<\");\n";
+ for (std::vector< OUString >::const_iterator i(
+ entity_->getTypeParameters().begin());
+ i != entity_->getTypeParameters().end();) {
+ out << indent()
+ << ("the_buffer.append(::rtl::OUStringToOString("
+ "::cppu::getTypeFavourChar(static_cast< ");
+ dumpTypeParameterName(out, *i);
+ out << " * >(0)).getTypeName(), RTL_TEXTENCODING_UTF8));\n";
+ ++i;
+ if (i != entity_->getTypeParameters().end()) {
+ out << indent() << "the_buffer.append(',');\n";
+ }
+ }
+ out << indent() << "the_buffer.append('>');\n";
+
+ out << "#endif\n";
+
+ out << indent()
+ << "::typelib_static_type_init(&the_type, " << getTypeClass(name_, true)
+ << ", the_buffer.getStr());\n";
+
+ dec();
+ out << indent() << "}\n" << indent()
+ << "return *reinterpret_cast< ::css::uno::Type * >(&the_type);\n";
+ dumpGetCppuTypePostamble(out);
+}
+
+void PolyStructType::dumpNormalGetCppuType(FileStream & out)
+{
+ dumpGetCppuTypePreamble(out);
+ out << indent()
+ << ("//TODO: On certain platforms with weak memory models, the"
+ " following code can result in some threads observing that the_type"
+ " points to garbage\n")
+ << indent()
+ << "static ::typelib_TypeDescriptionReference * the_type = 0;\n"
+ << indent() << "if (the_type == 0) {\n";
+ inc();
+ out << indent() << "::rtl::OStringBuffer the_buffer(\"" << name_
+ << "<\");\n";
+ for (std::vector< OUString >::const_iterator i(
+ entity_->getTypeParameters().begin());
+ i != entity_->getTypeParameters().end();) {
+ out << indent()
+ << ("the_buffer.append(::rtl::OUStringToOString("
+ "::cppu::getTypeFavourChar(static_cast< ");
+ dumpTypeParameterName(out, *i);
+ out << " * >(0)).getTypeName(), RTL_TEXTENCODING_UTF8));\n";
+ ++i;
+ if (i != entity_->getTypeParameters().end()) {
+ out << indent() << "the_buffer.append(',');\n";
+ }
+ }
+ out << indent() << "the_buffer.append('>');\n" << indent()
+ << "::typelib_TypeDescriptionReference * the_members[] = {\n";
+ inc();
+ for (std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ const_iterator i(entity_->getMembers().begin());
+ i != entity_->getMembers().end();) {
+ out << indent();
+ if (i->parameterized) {
+ out << "::cppu::getTypeFavourChar(static_cast< ";
+ dumpTypeParameterName(out, i->type);
+ out << " * >(0))";
+ } else {
+ out << "::cppu::UnoType< ";
+ dumpType(out, i->type, false, false, false, true);
+ out << " >::get()";
+ }
+ ++i;
+ out << ".getTypeLibType()"
+ << (i == entity_->getMembers().end() ? " };" : ",") << "\n";
+ }
+ dec();
+ out << indent() << "static ::sal_Bool const the_parameterizedTypes[] = { ";
+ for (std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ const_iterator i(entity_->getMembers().begin());
+ i != entity_->getMembers().end(); ++i) {
+ if (i != entity_->getMembers().begin()) {
+ out << ", ";
+ }
+ out << (i->parameterized ? "true" : "false");
+ }
+ out << " };\n" << indent()
+ << ("::typelib_static_struct_type_init(&the_type, the_buffer.getStr(),"
+ " 0, ")
+ << entity_->getMembers().size()
+ << ", the_members, the_parameterizedTypes);\n";
+ dec();
+ out << indent() << "}\n" << indent()
+ << ("return *reinterpret_cast< ::css::uno::Type * >("
+ "&the_type);\n");
+ dumpGetCppuTypePostamble(out);
+}
+
+void PolyStructType::dumpComprehensiveGetCppuType(FileStream & out)
+{
+ out << "namespace cppu { namespace detail {\n\n" << indent();
+ dumpTemplateHead(out);
+ OUString staticTypeClass("the" + id_ + "Type");
+ out << "struct " << staticTypeClass
+ << " : public rtl::StaticWithInit< ::css::uno::Type *, "
+ << staticTypeClass;
+ dumpTemplateParameters(out);
+ out << " >\n" << indent() << "{\n";
+ inc();
+ out << indent() << "::css::uno::Type * operator()() const\n"
+ << indent() << "{\n";
+ inc();
+
+ out << "#ifdef LIBO_INTERNAL_ONLY\n";
+ out << indent()
+ << "::rtl::OUString the_name =\n";
+ out << indent() << "\"" << name_ << "<\" +\n";
+ for (std::vector< OUString >::const_iterator i(
+ entity_->getTypeParameters().begin());
+ i != entity_->getTypeParameters().end();) {
+ out << indent()
+ << "::cppu::getTypeFavourChar(static_cast< ";
+ dumpTypeParameterName(out, *i);
+ out << " * >(0)).getTypeName() +\n";
+ ++i;
+ if (i != entity_->getTypeParameters().end()) {
+ out << indent()
+ << "\",\" +\n";
+ }
+ }
+ out << indent()
+ << "\">\";\n";
+ out << "#else\n";
+ out << indent() << "::rtl::OUStringBuffer the_buffer;\n" << indent()
+ << "the_buffer.append(\"" << name_ << "<\");\n";
+ for (std::vector< OUString >::const_iterator i(
+ entity_->getTypeParameters().begin());
+ i != entity_->getTypeParameters().end();) {
+ out << indent()
+ << "the_buffer.append(::cppu::getTypeFavourChar(static_cast< ";
+ dumpTypeParameterName(out, *i);
+ out << " * >(0)).getTypeName());\n";
+ ++i;
+ if (i != entity_->getTypeParameters().end()) {
+ out << indent()
+ << ("the_buffer.append("
+ "static_cast< ::sal_Unicode >(','));\n");
+ }
+ }
+ out << indent() << "the_buffer.append(static_cast< ::sal_Unicode >('>'));\n";
+ out << indent()
+ << "::rtl::OUString the_name(the_buffer.makeStringAndClear());\n";
+ out << "#endif\n";
+ std::map< OUString, sal_uInt32 > parameters;
+ std::map< OUString, sal_uInt32 > types;
+ std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ size_type n = 0;
+ for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity_->getMembers()) {
+ if (member.parameterized) {
+ if (parameters.emplace(
+ member.type, static_cast< sal_uInt32 >(parameters.size())).
+ second) {
+ sal_uInt32 k = static_cast< sal_uInt32 >(parameters.size() - 1);
+ out << indent()
+ << "::css::uno::Type const & the_ptype" << k
+ << " = ::cppu::getTypeFavourChar(static_cast< ";
+ dumpTypeParameterName(out, member.type);
+ out << " * >(0));\n" << indent()
+ << "::typelib_TypeClass the_pclass" << k
+ << " = (::typelib_TypeClass) the_ptype" << k
+ << ".getTypeClass();\n" << indent()
+ << "::rtl::OUString the_pname" << k << "(the_ptype" << k
+ << ".getTypeName());\n";
+ }
+ } else if (types.emplace(member.type, static_cast< sal_uInt32 >(types.size())).
+ second) {
+ dumpCppuGetType(out, member.type, &name_);
+ // For typedefs, use the resolved type name, as there will be no
+ // information available about the typedef itself at runtime (the
+ // above getCppuType call will make available information about the
+ // resolved type); no extra #include for the resolved type is
+ // needed, as the header for the typedef includes it already:
+ out << indent() << "::rtl::OUString the_tname"
+ << static_cast< sal_uInt32 >(types.size() - 1) << "( \""
+ << resolveAllTypedefs(member.type) << "\" );\n";
+ }
+ out << indent() << "::rtl::OUString the_name" << n++ << "( \""
+ << member.name << "\" );\n";
+ }
+ out << indent() << "::typelib_StructMember_Init the_members[] = {\n";
+ inc();
+ n = 0;
+ for (std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ const_iterator i(entity_->getMembers().begin());
+ i != entity_->getMembers().end();) {
+ out << indent() << "{ { ";
+ if (i->parameterized) {
+ sal_uInt32 k = parameters.find(i->type)->second;
+ out << "the_pclass" << k << ", the_pname" << k << ".pData";
+ } else {
+ out << getTypeClass(i->type, true) << ", the_tname"
+ << types.find(i->type)->second << ".pData";
+ }
+ out << ", the_name" << n++ << ".pData }, "
+ << (i->parameterized ? "true" : "false") << " }";
+ ++i;
+ out << (i == entity_->getMembers().end() ? " };" : ",") << "\n";
+ }
+ dec();
+ out << indent() << "::typelib_TypeDescription * the_newType = 0;\n";
+ out << indent()
+ << ("::typelib_typedescription_newStruct(&the_newType, the_name.pData,"
+ " 0, ")
+ << entity_->getMembers().size() << ", the_members);\n" << indent()
+ << "::typelib_typedescription_register(&the_newType);\n" << indent()
+ << "::typelib_typedescription_release(the_newType);\n" << indent()
+ << "return new ::css::uno::Type(" << getTypeClass(name_)
+ << ", the_name); // leaked\n";
+ dec();
+ out << indent() << "}\n";
+ dec();
+ out << indent() << "};\n } }\n\n";
+ dumpGetCppuTypePreamble(out);
+ out << indent() << "return *detail::" << staticTypeClass;
+ dumpTemplateParameters(out);
+ out << "::get();\n";
+ dumpGetCppuTypePostamble(out);
+}
+
+void PolyStructType::addLightGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ includes.addType();
+ includes.addCppuUnotypeHxx();
+ includes.addSalTypesH();
+ includes.addTypelibTypeclassH();
+ includes.addTypelibTypedescriptionH();
+ includes.addRtlStrbufHxx();
+ includes.addRtlTextencH();
+ includes.addRtlUstringHxx();
+}
+
+void PolyStructType::addNormalGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ includes.addType();
+ includes.addCppuUnotypeHxx();
+ includes.addSalTypesH();
+ includes.addTypelibTypeclassH();
+ includes.addTypelibTypedescriptionH();
+ includes.addRtlStrbufHxx();
+ includes.addRtlTextencH();
+ includes.addRtlUstringHxx();
+}
+
+void PolyStructType::addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ includes.addType();
+ includes.addCppuUnotypeHxx();
+ includes.addRtlInstanceHxx();
+ includes.addRtlUstringH();
+ includes.addRtlUstringHxx();
+ includes.addSalTypesH();
+ includes.addTypelibTypeclassH();
+ includes.addTypelibTypedescriptionH();
+ includes.addRtlStringH();
+ includes.addRtlUstrbufHxx();
+}
+
+void PolyStructType::dumpTemplateHead(FileStream & out) const
+{
+ out << "template< ";
+ for (std::vector< OUString >::const_iterator i(
+ entity_->getTypeParameters().begin());
+ i != entity_->getTypeParameters().end(); ++i) {
+ if (i != entity_->getTypeParameters().begin()) {
+ out << ", ";
+ }
+ out << "typename ";
+ dumpTypeParameterName(out, *i);
+ }
+ out << " > ";
+}
+
+void PolyStructType::dumpTemplateParameters(FileStream & out) const
+{
+ out << "< ";
+ for (std::vector< OUString >::const_iterator i(
+ entity_->getTypeParameters().begin());
+ i != entity_->getTypeParameters().end(); ++i) {
+ if (i != entity_->getTypeParameters().begin()) {
+ out << ", ";
+ }
+ dumpTypeParameterName(out, *i);
+ }
+ out << " >";
+}
+
+OUString typeToIdentifier(std::u16string_view name)
+{
+ sal_Int32 k;
+ OUString n(b2u(codemaker::UnoType::decompose(u2b(name), &k)));
+ OUStringBuffer b(4*k + n.getLength());
+ for (sal_Int32 i = 0; i != k; ++i) {
+ b.append("seq_");
+ }
+ b.append(n);
+ b.replace(' ', '_');
+ b.replace(',', '_');
+ b.replace('.', '_');
+ b.replace('<', '_');
+ b.replace('>', '_');
+ return b.makeStringAndClear();
+}
+
+class ExceptionType: public CppuType
+{
+public:
+ ExceptionType(
+ rtl::Reference< unoidl::ExceptionTypeEntity > const & entity,
+ OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
+ CppuType(name, typeMgr), entity_(entity) {
+ assert(entity.is());
+ }
+
+private:
+ virtual void dumpHdlFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes) override;
+
+ virtual void dumpHppFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes) override;
+
+ virtual void addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const override;
+
+ virtual void dumpLightGetCppuType(FileStream & out) override;
+
+ virtual void dumpNormalGetCppuType(FileStream & out) override;
+
+ virtual void dumpComprehensiveGetCppuType(FileStream & out) override;
+
+ virtual sal_uInt32 checkInheritedMemberCount() const override {
+ return getTotalMemberCount(entity_->getDirectBase());
+ }
+
+ virtual void dumpDeclaration(FileStream & out) override;
+
+ bool dumpBaseMembers(
+ FileStream & out, OUString const & base, bool withType,
+ bool eligibleForDefaults);
+
+ sal_uInt32 getTotalMemberCount(OUString const & base) const;
+
+ rtl::Reference< unoidl::ExceptionTypeEntity > entity_;
+};
+
+void ExceptionType::dumpHdlFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes)
+{
+ if (name_ == "com.sun.star.uno.Exception")
+ {
+ // LIBO_INTERNAL_ONLY implies GCC >= 7, which we need for this
+ // Merely checking __has_include is not enough because some systems have the header,
+ // but do not have a new enough Clang 9 supporting __builtin_FILE/LINE/FUNCTION as used by
+ // that libstdc++ header.
+ includes.addCustom("#if defined LIBO_INTERNAL_ONLY && ((defined __GNUC__ && !defined __clang__) || (defined __clang__ && __clang_major__ >= 9)) && __has_include(<experimental/source_location>)");
+ includes.addCustom("#define LIBO_USE_SOURCE_LOCATION");
+ includes.addCustom("#endif");
+ includes.addCustom("#if defined LIBO_USE_SOURCE_LOCATION");
+ includes.addCustom("#include <experimental/source_location>");
+ includes.addCustom("#include <o3tl/runtimetooustring.hxx>");
+ includes.addCustom("#endif");
+ }
+ dumpHFileContent(out, includes);
+}
+
+void ExceptionType::addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ includes.addCppuUnotypeHxx();
+ includes.addRtlInstanceHxx(); // using rtl::StaticWithInit
+}
+
+void ExceptionType::dumpHppFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes)
+{
+ OUString headerDefine(dumpHeaderDefine(out, u"HPP"));
+ out << "\n";
+ addDefaultHxxIncludes(includes);
+ includes.dump(out, &name_, true);
+
+ // for the output operator below
+ if (name_ == "com.sun.star.uno.Exception")
+ {
+ out << "#if defined LIBO_INTERNAL_ONLY\n";
+ out << "#include <ostream>\n";
+ out << "#include <typeinfo>\n";
+ out << "#endif\n";
+ }
+
+ out << "\n";
+
+ if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) {
+ out << "\n";
+ }
+
+ // default constructor
+ out << "\ninline " << id_ << "::" << id_ << "(\n";
+ out << "#if defined LIBO_USE_SOURCE_LOCATION\n";
+ out << " std::experimental::source_location location\n";
+ out << "#endif\n";
+ out << " )\n";
+ inc();
+ OUString base(entity_->getDirectBase());
+ bool bFirst = true;
+ if (!base.isEmpty()) {
+ out << indent() << ": " << codemaker::cpp::scopedCppName(u2b(base))
+ << "(\n";
+ out << "#if defined LIBO_USE_SOURCE_LOCATION\n";
+ out << " location\n";
+ out << "#endif\n";
+ out << ")\n";
+ bFirst = false;
+ }
+ for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
+ out << indent() << (bFirst ? ":" : ",") << " ";
+ out << member.name;
+ dumpInitializer(out, false, member.type);
+ out << "\n";
+ bFirst = false;
+ }
+ dec();
+ out << "{";
+ if (!m_cppuTypeDynamic) {
+ out << "\n";
+ inc();
+ dumpCppuGetType(out, name_);
+ dec();
+ } else {
+ out << " ";
+ }
+ if (name_ == "com.sun.star.uno.Exception")
+ {
+ out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n";
+ out << " if (!Message.isEmpty())\n";
+ out << " Message += \" \";\n";
+ out << " Message += \"at \" + o3tl::runtimeToOUString(location.file_name()) + \":\" + OUString::number(location.line());\n";
+ out << "#endif\n";
+ }
+ out << "}\n\n";
+
+ // fields constructor
+ if (!entity_->getDirectMembers().empty() || getInheritedMemberCount() > 0) {
+ out << indent() << "inline " << id_ << "::" << id_ << "(";
+ bFirst = !dumpBaseMembers(out, base, true, false);
+ for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
+ if (!bFirst) {
+ out << ", ";
+ }
+ dumpType(out, member.type, true, true);
+ out << " " << member.name << "_";
+ bFirst = false;
+ }
+ out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n";
+ out << " " << (bFirst ? "" : ", ") << "std::experimental::source_location location\n";
+ out << "#endif\n";
+ out << ")\n";
+ inc();
+ bFirst = true;
+ if (!base.isEmpty()) {
+ out << indent() << ": " << codemaker::cpp::scopedCppName(u2b(base))
+ << "(";
+ dumpBaseMembers(out, base, false, false);
+ out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n";
+ out << " , location\n";
+ out << "#endif\n";
+ out << ")\n";
+ bFirst = false;
+ }
+ for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
+ out << indent() << (bFirst ? ":" : ",") << " " << member.name << "("
+ << member.name << "_)\n";
+ bFirst = false;
+ }
+ dec();
+ out << "{";
+ if (!m_cppuTypeDynamic) {
+ out << "\n";
+ inc();
+ dumpCppuGetType(out, name_);
+ dec();
+ } else {
+ out << " ";
+ }
+ if (name_ == "com.sun.star.uno.Exception")
+ {
+ out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n";
+ out << " if (!Message.isEmpty())\n";
+ out << " Message += \" \";\n";
+ out << " Message += \"at \" + o3tl::runtimeToOUString(location.file_name()) + \":\" + OUString::number(location.line());\n";
+ out << "#endif\n";
+ }
+ out << "}\n\n";
+ }
+ out << "#if !defined LIBO_INTERNAL_ONLY\n" << indent() << id_ << "::" << id_
+ << "(" << id_ << " const & the_other)";
+ bFirst = true;
+ if (!base.isEmpty()) {
+ out << ": " << codemaker::cpp::scopedCppName(u2b(base))
+ << "(the_other)";
+ bFirst = false;
+ }
+ for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
+ out << (bFirst ? ":" : ",") << " " << member.name << "(the_other." << member.name
+ << ")";
+ bFirst = false;
+ }
+ out << indent() << " {}\n\n" << indent() << id_ << "::~" << id_
+ << "() {}\n\n" << indent() << id_ << " & " << id_ << "::operator =("
+ << id_ << " const & the_other) {\n";
+ inc();
+ out << indent()
+ << ("//TODO: Just like its implicitly-defined counterpart, this"
+ " function definition is not exception-safe\n");
+ if (!base.isEmpty()) {
+ out << indent() << codemaker::cpp::scopedCppName(u2b(base))
+ << "::operator =(the_other);\n";
+ }
+ for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
+ out << indent() << member.name << " = the_other." << member.name << ";\n";
+ }
+ out << indent() << "return *this;\n";
+ dec();
+ out << indent() << "}\n#endif\n\n";
+
+ // Provide an output operator for printing Exception information to SAL_WARN/SAL_INFO.
+ if (name_ == "com.sun.star.uno.Exception")
+ {
+ out << "#if defined LIBO_INTERNAL_ONLY\n";
+ out << "template< typename charT, typename traits >\n";
+ out << "inline ::std::basic_ostream<charT, traits> & operator<<(\n";
+ out << " ::std::basic_ostream<charT, traits> & os, ::com::sun::star::uno::Exception const & exception)\n";
+ out << "{\n";
+ out << " // the class name is useful because exception throwing code does not always pass in a useful message\n";
+ out << " os << typeid(exception).name();\n";
+ out << " if (!exception.Message.isEmpty())\n";
+ out << " os << \" msg: \" << exception.Message;\n";
+ out << " return os;\n";
+ out << "}\n";
+ out << "#endif\n";
+ out << "\n";
+ }
+
+ if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) {
+ out << "\n";
+ }
+ out << "\n";
+
+ dumpGetCppuType(out);
+ out << "\n#endif // "<< headerDefine << "\n";
+}
+
+void ExceptionType::dumpLightGetCppuType(FileStream & out)
+{
+ dumpGetCppuTypePreamble(out);
+ out << indent()
+ << "static typelib_TypeDescriptionReference * the_type = 0;\n"
+ << indent() << "if ( !the_type )\n" << indent() << "{\n";
+ inc();
+ out << indent() << "typelib_static_type_init( &the_type, "
+ << getTypeClass(name_, true) << ", \"" << name_ << "\" );\n";
+ dec();
+ out << indent() << "}\n" << indent()
+ << ("return * reinterpret_cast< ::css::uno::Type * >("
+ " &the_type );\n");
+ dumpGetCppuTypePostamble(out);
+}
+
+void ExceptionType::dumpNormalGetCppuType(FileStream & out)
+{
+ dumpGetCppuTypePreamble(out);
+ out << indent()
+ << "static typelib_TypeDescriptionReference * the_type = 0;\n"
+ << indent() << "if ( !the_type )\n" << indent() << "{\n";
+ inc();
+ OUString base(entity_->getDirectBase());
+ bool baseException = false;
+ if (!base.isEmpty()) {
+ if (base == "com.sun.star.uno.Exception") {
+ baseException = true;
+ } else {
+ out << indent()
+ << ("const ::css::uno::Type& rBaseType ="
+ " ::cppu::UnoType< ");
+ dumpType(out, base, true, false, false, true);
+ out << " >::get();\n\n";
+ }
+ }
+ if (!entity_->getDirectMembers().empty()) {
+ out << indent() << "typelib_TypeDescriptionReference * aMemberRefs["
+ << entity_->getDirectMembers().size() << "];\n";
+ std::set< OUString > seen;
+ std::vector< unoidl::ExceptionTypeEntity::Member >::size_type n = 0;
+ for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
+ OUString type(resolveAllTypedefs(member.type));
+ OUString modType(typeToIdentifier(type));
+ if (seen.insert(type).second) {
+ out << indent()
+ << "const ::css::uno::Type& rMemberType_"
+ << modType << " = ::cppu::UnoType< ";
+ dumpType(out, type, false, false, false, true);
+ out << " >::get();\n";
+ }
+ out << indent() << "aMemberRefs[" << n++ << "] = rMemberType_"
+ << modType << ".getTypeLibType();\n";
+ }
+ out << "\n";
+ }
+ out << indent() << "typelib_static_compound_type_init( &the_type, "
+ << getTypeClass(name_, true) << ", \"" << name_ << "\", ";
+ if (baseException) {
+ out << ("* ::typelib_static_type_getByTypeClass("
+ " typelib_TypeClass_EXCEPTION )");
+ } else if (base.isEmpty()) {
+ out << "0";
+ } else {
+ out << "rBaseType.getTypeLibType()";
+ }
+ out << ", " << entity_->getDirectMembers().size() << ", "
+ << (entity_->getDirectMembers().empty() ? "0" : "aMemberRefs")
+ << " );\n";
+ dec();
+ out << indent() << "}\n" << indent()
+ << ("return * reinterpret_cast< const ::css::uno::Type * >("
+ " &the_type );\n");
+ dumpGetCppuTypePostamble(out);
+}
+
+void ExceptionType::dumpComprehensiveGetCppuType(FileStream & out)
+{
+ codemaker::cppumaker::dumpNamespaceOpen(out, name_, false);
+ out << " namespace detail {\n\n";
+ OUString staticTypeClass("the" + id_ + "Type");
+ out << indent() << "struct " << staticTypeClass
+ << " : public rtl::StaticWithInit< ::css::uno::Type *, "
+ << staticTypeClass << " >\n" << indent() << "{\n";
+ inc();
+ out << indent() << "::css::uno::Type * operator()() const\n"
+ << indent() << "{\n";
+ inc();
+ out << indent() << "::rtl::OUString sTypeName( \"" << name_ << "\" );\n\n"
+ << indent() << "// Start inline typedescription generation\n"
+ << indent() << "typelib_TypeDescription * pTD = 0;\n";
+ OUString base(entity_->getDirectBase());
+ if (!base.isEmpty()) {
+ out << indent()
+ << ("const ::css::uno::Type& rSuperType ="
+ " ::cppu::UnoType< ");
+ dumpType(out, base, false, false, false, true);
+ out << " >::get();\n";
+ }
+ std::set< OUString > seen;
+ for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
+ if (seen.insert(member.type).second) {
+ dumpCppuGetType(out, member.type);
+ }
+ }
+ if (!entity_->getDirectMembers().empty()) {
+ out << "\n" << indent() << "typelib_CompoundMember_Init aMembers["
+ << entity_->getDirectMembers().size() << "];\n";
+ std::vector< unoidl::ExceptionTypeEntity::Member >::size_type n = 0;
+ for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
+ OUString type(resolveAllTypedefs(member.type));
+ out << indent() << "::rtl::OUString sMemberType" << n << "( \""
+ << type << "\" );\n" << indent()
+ << "::rtl::OUString sMemberName" << n << "( \"" << member.name
+ << "\" );\n" << indent() << "aMembers[" << n
+ << "].eTypeClass = (typelib_TypeClass)" << getTypeClass(type)
+ << ";\n" << indent() << "aMembers[" << n
+ << "].pTypeName = sMemberType" << n << ".pData;\n" << indent()
+ << "aMembers[" << n << "].pMemberName = sMemberName" << n
+ << ".pData;\n";
+ ++n;
+ }
+ }
+ out << "\n" << indent() << "typelib_typedescription_new(\n";
+ inc();
+ out << indent() << "&pTD,\n" << indent() << "(typelib_TypeClass)"
+ << getTypeClass(name_) << ", sTypeName.pData,\n" << indent()
+ << (base.isEmpty() ? "0" : "rSuperType.getTypeLibType()") << ",\n"
+ << indent() << entity_->getDirectMembers().size() << ",\n" << indent()
+ << (entity_->getDirectMembers().empty() ? "0" : "aMembers")
+ << " );\n\n";
+ dec();
+ out << indent()
+ << ("typelib_typedescription_register( (typelib_TypeDescription**)&pTD"
+ " );\n\n")
+ << indent() << "typelib_typedescription_release( pTD );\n" << indent()
+ << "// End inline typedescription generation\n\n" << indent()
+ << "return new ::css::uno::Type( " << getTypeClass(name_)
+ << ", sTypeName ); // leaked\n";
+ dec();
+ out << indent() << "}\n";
+ dec();
+ out << indent() << "};\n\n";
+ codemaker::cppumaker::dumpNamespaceClose(out, name_, false);
+ out << " }\n\n";
+ dumpGetCppuTypePreamble(out);
+ out << indent() << "return *detail::" << staticTypeClass << "::get();\n";
+ dumpGetCppuTypePostamble(out);
+}
+
+void ExceptionType::dumpDeclaration(FileStream & out)
+{
+ out << "\nclass CPPU_GCC_DLLPUBLIC_EXPORT SAL_WARN_UNUSED " << id_;
+ OUString base(entity_->getDirectBase());
+ if (!base.isEmpty()) {
+ out << " : public " << codemaker::cpp::scopedCppName(u2b(base));
+ }
+ out << "\n{\npublic:\n";
+ inc();
+
+ // default constructor
+ out << indent() << "inline CPPU_GCC_DLLPRIVATE " << id_ << "(\n";
+ out << "#if defined LIBO_USE_SOURCE_LOCATION\n";
+ out << " std::experimental::source_location location = std::experimental::source_location::current()\n";
+ out << "#endif\n\n";
+ out << " );\n";
+
+ // constructor that initializes data members
+ if (!entity_->getDirectMembers().empty() || getInheritedMemberCount() > 0) {
+ out << indent() << "inline CPPU_GCC_DLLPRIVATE " << id_ << "(";
+ bool eligibleForDefaults = entity_->getDirectMembers().empty();
+ bool bFirst = !dumpBaseMembers(out, base, true, eligibleForDefaults);
+ for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
+ if (!bFirst) {
+ out << ", ";
+ }
+ dumpType(out, member.type, true, true);
+ out << " " << member.name << "_";
+ bFirst = false;
+ }
+ out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n";
+ out << ", std::experimental::source_location location = std::experimental::source_location::current()\n";
+ out << "#endif\n";
+ out << " );\n\n";
+ }
+ out << "#if !defined LIBO_INTERNAL_ONLY\n" << indent()
+ << "inline CPPU_GCC_DLLPRIVATE " << id_ << "(" << id_
+ << " const &);\n\n" << indent() << "inline CPPU_GCC_DLLPRIVATE ~"
+ << id_ << "();\n\n" << indent() << "inline CPPU_GCC_DLLPRIVATE " << id_
+ << " & operator =(" << id_ << " const &);\n#endif\n\n";
+ for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
+ entity_->getDirectMembers().begin());
+ i != entity_->getDirectMembers().end(); ++i) {
+ out << indent();
+ dumpType(out, i->type);
+ out << " " << i->name;
+ if (i == entity_->getDirectMembers().begin() && !base.isEmpty()
+ && i->type != "hyper" && i->type != "unsigned hyper"
+ && i->type != "double") {
+ out << " CPPU_GCC3_ALIGN( "
+ << codemaker::cpp::scopedCppName(u2b(base)) << " )";
+ }
+ out << ";\n";
+ }
+ dec();
+ out << "};\n\n";
+}
+
+bool ExceptionType::dumpBaseMembers(
+ FileStream & out, OUString const & base, bool withType, bool eligibleForDefaults)
+{
+ if (base.isEmpty())
+ return false;
+
+ bool hasMember = false;
+ rtl::Reference< unoidl::Entity > ent;
+ codemaker::UnoType::Sort sort = m_typeMgr->getSort(base, &ent);
+ if (sort != codemaker::UnoType::Sort::Exception) {
+ throw CannotDumpException(
+ "exception type base " + base + " is not an exception type");
+ }
+ rtl::Reference< unoidl::ExceptionTypeEntity > ent2(
+ dynamic_cast< unoidl::ExceptionTypeEntity * >(ent.get()));
+ assert(ent2.is());
+ if (!ent2.is()) {
+ return false;
+ }
+ hasMember = dumpBaseMembers( out, ent2->getDirectBase(), withType,
+ eligibleForDefaults && ent2->getDirectMembers().empty() );
+ int memberCount = 0;
+ for (const unoidl::ExceptionTypeEntity::Member& member : ent2->getDirectMembers()) {
+ if (hasMember) {
+ out << ", ";
+ }
+ if (withType) {
+ dumpType(out, member.type, true, true);
+ out << " ";
+ }
+ out << member.name << "_";
+ // We want to provide a default parameter value for uno::Exception subtype
+ // constructors, since most of the time we don't pass a Context object in to the exception
+ // throw sites.
+ if (eligibleForDefaults
+ && base == "com.sun.star.uno.Exception"
+ && memberCount == 1
+ && member.name == "Context"
+ && member.type == "com.sun.star.uno.XInterface") {
+ out << " = ::css::uno::Reference< ::css::uno::XInterface >()";
+ }
+ hasMember = true;
+ ++memberCount;
+ }
+ return hasMember;
+}
+
+sal_uInt32 ExceptionType::getTotalMemberCount(OUString const & base) const
+{
+ if (base.isEmpty()) {
+ return 0;
+ }
+ rtl::Reference< unoidl::Entity > ent;
+ codemaker::UnoType::Sort sort = m_typeMgr->getSort(base, &ent);
+ if (sort != codemaker::UnoType::Sort::Exception) {
+ throw CannotDumpException(
+ "exception type base " + base + " is not an exception type");
+ }
+ unoidl::ExceptionTypeEntity& ent2(dynamic_cast<unoidl::ExceptionTypeEntity&>(*ent));
+ return getTotalMemberCount(ent2.getDirectBase())
+ + ent2.getDirectMembers().size(); //TODO: overflow
+}
+
+class EnumType: public CppuType
+{
+public:
+ EnumType(
+ rtl::Reference< unoidl::EnumTypeEntity > const & entity,
+ OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
+ CppuType(name, typeMgr), entity_(entity) {
+ assert(entity.is());
+ }
+
+private:
+ virtual void dumpDeclaration(FileStream& o) override;
+
+ virtual void addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const override;
+
+ void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
+
+ void dumpNormalGetCppuType(FileStream& o) override;
+ void dumpComprehensiveGetCppuType(FileStream& o) override;
+
+ rtl::Reference< unoidl::EnumTypeEntity > entity_;
+};
+
+void EnumType::addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ includes.addCppuUnotypeHxx();
+ includes.addRtlInstanceHxx(); // using rtl::StaticWithInit
+}
+
+void EnumType::dumpDeclaration(FileStream& o)
+{
+ o << "\n#if defined LIBO_INTERNAL_ONLY\n";
+ o << "\nenum class SAL_DLLPUBLIC_RTTI " << id_ << "\n{\n";
+ o << "\n#else\n";
+ o << "\nenum SAL_DLLPUBLIC_RTTI " << id_ << "\n{\n";
+ o << "\n#endif\n";
+ inc();
+
+ for (const unoidl::EnumTypeEntity::Member& member : entity_->getMembers()) {
+ o << indent() << id_ << "_" << u2b(member.name) << " = " << member.value
+ << ",\n";
+ }
+
+ o << indent() << id_ << "_MAKE_FIXED_SIZE = SAL_MAX_ENUM\n";
+
+ dec();
+ o << "};\n\n";
+
+ // use constexpr to create a kind of type-alias so we don't have to modify existing code
+ o << "#if defined LIBO_INTERNAL_ONLY\n";
+ for (const unoidl::EnumTypeEntity::Member& member : entity_->getMembers()) {
+ o << "constexpr auto " << id_ << "_" << u2b(member.name)
+ << " = "
+ << id_ << "::" << id_ << "_" << u2b(member.name)
+ << ";\n";
+ }
+ o << "#endif\n";
+}
+
+void EnumType::dumpHppFile(
+ FileStream& o, codemaker::cppumaker::Includes & includes)
+{
+ OUString headerDefine(dumpHeaderDefine(o, u"HPP"));
+ o << "\n";
+
+ addDefaultHxxIncludes(includes);
+ includes.dump(o, &name_, true);
+ o << "\n";
+
+ dumpGetCppuType(o);
+
+ o << "\n#endif // "<< headerDefine << "\n";
+}
+
+void EnumType::dumpNormalGetCppuType(FileStream& o)
+{
+ dumpGetCppuTypePreamble(o);
+
+ o << indent()
+ << "static typelib_TypeDescriptionReference * the_type = 0;\n";
+
+ o << indent() << "if ( !the_type )\n" << indent() << "{\n";
+ inc();
+
+ o << indent() << "typelib_static_enum_type_init( &the_type,\n";
+ inc(31);
+ o << indent() << "\"" << name_ << "\",\n"
+ << indent() << codemaker::cpp::scopedCppName(u2b(name_)) << "_"
+ << u2b(entity_->getMembers()[0].name) << " );\n";
+ dec(31);
+ dec();
+ o << indent() << "}\n";
+ o << indent()
+ << ("return * reinterpret_cast< ::css::uno::Type * >("
+ " &the_type );\n");
+ dumpGetCppuTypePostamble(o);
+}
+
+void EnumType::dumpComprehensiveGetCppuType(FileStream& o)
+{
+ if (!isPolymorphic())
+ codemaker::cppumaker::dumpNamespaceOpen(o, name_, false);
+ else
+ o << "namespace cppu { ";
+ o << " namespace detail {\n\n";
+
+ OUString sStaticTypeClass("the" + id_ + "Type");
+ o << indent() << "struct " << sStaticTypeClass << " : public rtl::StaticWithInit< ::css::uno::Type *, " << sStaticTypeClass << " >\n";
+ o << indent() << "{\n";
+ inc();
+ o << indent() << "::css::uno::Type * operator()() const\n";
+ o << indent() << "{\n";
+
+ inc();
+ o << indent() << "::rtl::OUString sTypeName( \"" << name_
+ << "\" );\n\n";
+
+ o << indent() << "// Start inline typedescription generation\n"
+ << indent() << "typelib_TypeDescription * pTD = 0;\n\n";
+
+ o << indent() << "rtl_uString* enumValueNames["
+ << entity_->getMembers().size() << "];\n";
+ std::vector< unoidl::EnumTypeEntity::Member >::size_type n = 0;
+ for (const unoidl::EnumTypeEntity::Member& member : entity_->getMembers()) {
+ o << indent() << "::rtl::OUString sEnumValue" << n << "( \""
+ << u2b(member.name) << "\" );\n";
+ o << indent() << "enumValueNames[" << n << "] = sEnumValue" << n
+ << ".pData;\n";
+ ++n;
+ }
+
+ o << "\n" << indent() << "sal_Int32 enumValues["
+ << entity_->getMembers().size() << "];\n";
+ n = 0;
+ for (const unoidl::EnumTypeEntity::Member& member : entity_->getMembers()) {
+ o << indent() << "enumValues[" << n++ << "] = " << member.value << ";\n";
+ }
+
+ o << "\n" << indent() << "typelib_typedescription_newEnum( &pTD,\n";
+ inc();
+ o << indent() << "sTypeName.pData,\n"
+ << indent() << "(sal_Int32)"
+ << codemaker::cpp::scopedCppName(u2b(name_), false) << "_"
+ << u2b(entity_->getMembers()[0].name) << ",\n"
+ << indent() << entity_->getMembers().size()
+ << ", enumValueNames, enumValues );\n\n";
+ dec();
+
+ o << indent()
+ << ("typelib_typedescription_register( (typelib_TypeDescription**)&pTD"
+ " );\n");
+ o << indent() << "typelib_typedescription_release( pTD );\n"
+ << indent() << "// End inline typedescription generation\n\n";
+
+ o << indent() << "return new ::css::uno::Type( "
+ << getTypeClass(name_) << ", sTypeName ); // leaked\n";
+
+ dec();
+ o << indent() << "}\n";
+ dec();
+ o << indent() << "};\n\n";
+
+ if (!isPolymorphic())
+ codemaker::cppumaker::dumpNamespaceClose(o, name_, false);
+ else
+ o << " }";
+ o << " }\n\n";
+
+ dumpGetCppuTypePreamble(o);
+ o << indent() << "return *detail::" << sStaticTypeClass << "::get();\n";
+ dumpGetCppuTypePostamble(o);
+}
+
+class Typedef: public CppuType
+{
+public:
+ Typedef(
+ rtl::Reference< unoidl::TypedefEntity > const & entity,
+ OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
+ CppuType(name, typeMgr), entity_(entity) {
+ assert(entity.is());
+ }
+
+private:
+ virtual void dumpDeclaration(FileStream& o) override;
+
+ void dumpHdlFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
+
+ void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
+
+ rtl::Reference< unoidl::TypedefEntity > entity_;
+};
+
+void Typedef::dumpHdlFile(
+ FileStream& o, codemaker::cppumaker::Includes & includes)
+{
+ OUString headerDefine(dumpHeaderDefine(o, u"HDL"));
+ o << "\n";
+
+ addDefaultHIncludes(includes);
+ includes.dump(o, nullptr, true);
+ o << "\n";
+
+ if (codemaker::cppumaker::dumpNamespaceOpen(o, name_, false)) {
+ o << "\n";
+ }
+
+ dumpDeclaration(o);
+
+ if (codemaker::cppumaker::dumpNamespaceClose(o, name_, false)) {
+ o << "\n";
+ }
+
+ o << "#endif // "<< headerDefine << "\n";
+}
+
+void Typedef::dumpDeclaration(FileStream& o)
+{
+ o << "\ntypedef ";
+ dumpType(o, entity_->getType());
+ o << " " << id_ << ";\n\n";
+}
+
+void Typedef::dumpHppFile(
+ FileStream& o, codemaker::cppumaker::Includes & includes)
+{
+ OUString headerDefine(dumpHeaderDefine(o, u"HPP"));
+ o << "\n";
+
+ addDefaultHxxIncludes(includes);
+ includes.dump(o, &name_, true);
+ o << "\n";
+
+ o << "\n#endif // "<< headerDefine << "\n";
+}
+
+class ConstructiveType: public CppuType
+{
+public:
+ ConstructiveType(
+ OUString const & name, rtl::Reference< TypeManager > const & manager):
+ CppuType(name, manager) {}
+
+private:
+ virtual void dumpHdlFile(FileStream &, codemaker::cppumaker::Includes &) override {
+ assert(false); // this cannot happen
+ }
+
+ virtual void dumpFiles(OUString const & uri, CppuOptions const & options) override {
+ dumpFile(uri, name_, true, options);
+ }
+};
+
+bool hasRestParameter(
+ unoidl::SingleInterfaceBasedServiceEntity::Constructor const & constructor)
+{
+ return !constructor.parameters.empty()
+ && constructor.parameters.back().rest;
+}
+
+void includeExceptions(
+ codemaker::cppumaker::Includes & includes,
+ codemaker::ExceptionTreeNode const * node)
+{
+ if (node->present) {
+ includes.add(node->name);
+ } else {
+ for (std::unique_ptr<codemaker::ExceptionTreeNode> const & pChild : node->children) {
+ includeExceptions(includes, pChild.get());
+ }
+ }
+}
+
+class ServiceType: public ConstructiveType
+{
+public:
+ ServiceType(
+ rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > const &
+ entity,
+ OUString const & name, rtl::Reference< TypeManager > const & manager):
+ ConstructiveType(name, manager), entity_(entity) {
+ assert(entity.is());
+ }
+
+private:
+ virtual void dumpHppFile(
+ FileStream & o, codemaker::cppumaker::Includes & includes) override;
+
+ void dumpCatchClauses(
+ FileStream & out, codemaker::ExceptionTreeNode const * node);
+
+ rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > entity_;
+};
+
+void failsToSupply(
+ FileStream & o, std::u16string_view service, OString const & type)
+{
+ o << "::rtl::OUString(\"component context fails to supply service \") + \""
+ << service << "\" + \" of type \" + \"" << type << "\"";
+}
+
+void ServiceType::dumpHppFile(
+ FileStream & o, codemaker::cppumaker::Includes & includes)
+{
+ if (!entity_->getConstructors().empty()) {
+ //TODO: Decide whether the types added to includes should rather be
+ // added to m_dependencies (and thus be generated during
+ // dumpDependedTypes):
+ includes.addCassert();
+ includes.addReference();
+ includes.addRtlUstringH();
+ includes.addRtlUstringHxx();
+ includes.add("com.sun.star.uno.DeploymentException");
+ includes.add("com.sun.star.uno.XComponentContext");
+ for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor& cons : entity_->getConstructors()) {
+ if (cons.defaultConstructor) {
+ includes.add("com.sun.star.uno.Exception");
+ includes.add("com.sun.star.uno.RuntimeException");
+ } else {
+ if (!hasRestParameter(cons)) {
+ includes.addAny();
+ includes.addSequence();
+ for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter& param :
+ cons.parameters) {
+ if (m_typeMgr->getSort(
+ b2u(codemaker::UnoType::decompose(
+ u2b(param.type))))
+ == codemaker::UnoType::Sort::Char) {
+ includes.addCppuUnotypeHxx();
+ break;
+ }
+ }
+ }
+ codemaker::ExceptionTree tree;
+ for (const OUString& ex : cons.exceptions) {
+ tree.add(u2b(ex), m_typeMgr);
+ }
+ if (!tree.getRoot().present) {
+ includes.add("com.sun.star.uno.Exception");
+ includes.add("com.sun.star.uno.RuntimeException");
+ includeExceptions(includes, &tree.getRoot());
+ }
+ }
+ }
+ }
+ OString cppName(
+ codemaker::cpp::translateUnoToCppIdentifier(
+ u2b(id_), "service", isGlobal()));
+ OUString headerDefine(dumpHeaderDefine(o, u"HPP"));
+ o << "\n";
+ includes.dump(o, nullptr, true);
+ if (!entity_->getConstructors().empty()) {
+ o << ("\n#if defined ANDROID || defined IOS //TODO\n"
+ "#include <com/sun/star/lang/XInitialization.hpp>\n"
+ "#include <osl/detail/component-defines.h>\n#endif\n\n"
+ "#if defined LO_URE_CURRENT_ENV && defined LO_URE_CTOR_ENV_")
+ << name_.replaceAll(".", "_dot_")
+ << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_"
+ << name_.replaceAll(".", "_dot_") << ") && defined LO_URE_CTOR_FUN_"
+ << name_.replaceAll(".", "_dot_")
+ << "\nextern \"C\" ::css::uno::XInterface * SAL_CALL LO_URE_CTOR_FUN_"
+ << name_.replaceAll(".", "_dot_")
+ << "(::css::uno::XComponentContext *, ::css::uno::Sequence< "
+ "::css::uno::Any > const &);\n#endif\n";
+ }
+ o << "\n";
+ if (codemaker::cppumaker::dumpNamespaceOpen(o, name_, false)) {
+ o << "\n";
+ }
+ o << "\nclass " << cppName << " {\n";
+ inc();
+ if (!entity_->getConstructors().empty()) {
+ OString baseName(u2b(entity_->getBase()));
+ OString scopedBaseName(codemaker::cpp::scopedCppName(baseName));
+ o << "public:\n";
+ for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor& cons :
+ entity_->getConstructors()) {
+ if (cons.defaultConstructor) {
+ o << indent() << "static ::css::uno::Reference< "
+ << scopedBaseName << " > "
+ << codemaker::cpp::translateUnoToCppIdentifier(
+ "create", "method", codemaker::cpp::IdentifierTranslationMode::NonGlobal,
+ &cppName)
+ << ("(::css::uno::Reference< ::css::uno::XComponentContext > const &"
+ " the_context) {\n");
+ inc();
+ o << indent() << "assert(the_context.is());\n" << indent()
+ << "::css::uno::Reference< " << scopedBaseName
+ << " > the_instance;\n" << indent() << "try {\n";
+ inc();
+ o << ("#if defined LO_URE_CURRENT_ENV && defined "
+ "LO_URE_CTOR_ENV_")
+ << name_.replaceAll(".", "_dot_")
+ << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_"
+ << name_.replaceAll(".", "_dot_")
+ << ") && defined LO_URE_CTOR_FUN_"
+ << name_.replaceAll(".", "_dot_") << "\n" << indent()
+ << "the_instance = ::css::uno::Reference< " << scopedBaseName
+ << (" >(::css::uno::Reference< ::css::uno::XInterface >("
+ "static_cast< ::css::uno::XInterface * >((*"
+ "LO_URE_CTOR_FUN_")
+ << name_.replaceAll(".", "_dot_")
+ << (")(the_context.get(), ::css::uno::Sequence<"
+ " ::css::uno::Any >())), ::SAL_NO_ACQUIRE),"
+ " ::css::uno::UNO_QUERY);\n#else\n")
+ << indent() << "the_instance = ::css::uno::Reference< "
+ << scopedBaseName
+ << (" >(the_context->getServiceManager()->"
+ "createInstanceWithContext("
+ " \"")
+ << name_
+ << "\", the_context), ::css::uno::UNO_QUERY);\n#endif\n";
+ dec();
+ o << indent()
+ << "} catch (const ::css::uno::RuntimeException &) {\n";
+ inc();
+ o << indent() << "throw;\n";
+ dec();
+ o << indent()
+ << "} catch (const ::css::uno::Exception & the_exception) {\n";
+ inc();
+ o << indent() << "throw ::css::uno::DeploymentException(";
+ failsToSupply(o, name_, baseName);
+ o << " + \": \" + the_exception.Message, the_context);\n";
+ dec();
+ o << indent() << "}\n" << indent()
+ << "if (!the_instance.is()) {\n";
+ inc();
+ o << indent() << "throw ::css::uno::DeploymentException(";
+ failsToSupply(o, name_, baseName);
+ o << ", the_context);\n";
+ dec();
+ o << indent() << "}\n" << indent() << "return the_instance;\n";
+ dec();
+ o << indent() << "}\n\n";
+ } else {
+ o << indent() << "static ::css::uno::Reference< "
+ << scopedBaseName << " > "
+ << codemaker::cpp::translateUnoToCppIdentifier(
+ u2b(cons.name), "method", codemaker::cpp::IdentifierTranslationMode::NonGlobal,
+ &cppName)
+ << ("(::css::uno::Reference< ::css::uno::XComponentContext > const &"
+ " the_context");
+ bool rest = hasRestParameter(cons);
+ for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter& param :
+ cons.parameters) {
+ o << ", ";
+ OUStringBuffer buf(2 + param.type.getLength());
+ if (param.rest) {
+ buf.append("[]");
+ }
+ buf.append(param.type);
+ OUString type(buf.makeStringAndClear());
+ bool byRef = passByReference(type);
+ dumpType(o, type, byRef, byRef);
+ o << " "
+ << codemaker::cpp::translateUnoToCppIdentifier(
+ u2b(param.name), "param", codemaker::cpp::IdentifierTranslationMode::NonGlobal);
+ }
+ o << ") {\n";
+ inc();
+ o << indent() << "assert(the_context.is());\n";
+ if (!rest && !cons.parameters.empty()) {
+ o << indent()
+ << "::css::uno::Sequence< ::css::uno::Any > the_arguments("
+ << cons.parameters.size() << ");\n";
+ o << indent()
+ << "::css::uno::Any* the_arguments_array = the_arguments.getArray();\n";
+
+ std::vector<
+ unoidl::SingleInterfaceBasedServiceEntity::Constructor::
+ Parameter >::size_type n = 0;
+ for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter& j :
+ cons.parameters) {
+ o << indent() << "the_arguments_array[" << n++ << "] ";
+ OString param(
+ codemaker::cpp::translateUnoToCppIdentifier(
+ u2b(j.name), "param",
+ codemaker::cpp::IdentifierTranslationMode::NonGlobal));
+ sal_Int32 rank;
+ if (resolveOuterTypedefs(j.type) == "any") {
+ o << "= " << param;
+ } else if (m_typeMgr->getSort(
+ b2u(codemaker::UnoType::decompose(
+ u2b(j.type), &rank)))
+ == codemaker::UnoType::Sort::Char) {
+ o << "= ::css::uno::Any(&" << param
+ << ", ::cppu::UnoType< ";
+ for (sal_Int32 k = 0; k < rank; ++k) {
+ o << "::cppu::UnoSequenceType< ";
+ }
+ o << "::cppu::UnoCharType";
+ for (sal_Int32 k = 0; k < rank; ++k) {
+ o << " >";
+ }
+ o << " >::get())";
+ } else {
+ o << "<<= " << param;
+ }
+ o << ";\n";
+ }
+ }
+ o << indent() << "::css::uno::Reference< "
+ << scopedBaseName << " > the_instance;\n";
+ codemaker::ExceptionTree tree;
+ for (const OUString& ex : cons.exceptions) {
+ tree.add(u2b(ex), m_typeMgr);
+ }
+ if (!tree.getRoot().present) {
+ o << indent() << "try {\n";
+ inc();
+ }
+ o << ("#if defined LO_URE_CURRENT_ENV && defined "
+ "LO_URE_CTOR_ENV_")
+ << name_.replaceAll(".", "_dot_")
+ << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_"
+ << name_.replaceAll(".", "_dot_")
+ << ") && defined LO_URE_CTOR_FUN_"
+ << name_.replaceAll(".", "_dot_") << "\n" << indent()
+ << "the_instance = ::css::uno::Reference< " << scopedBaseName
+ << (" >(::css::uno::Reference< ::css::uno::XInterface >("
+ "static_cast< ::css::uno::XInterface * >((*"
+ "LO_URE_CTOR_FUN_")
+ << name_.replaceAll(".", "_dot_")
+ << ")(the_context.get(), ";
+ if (rest) {
+ o << codemaker::cpp::translateUnoToCppIdentifier(
+ u2b(cons.parameters.back().name), "param",
+ codemaker::cpp::IdentifierTranslationMode::NonGlobal);
+ } else if (cons.parameters.empty()) {
+ o << "::css::uno::Sequence< ::css::uno::Any >()";
+ } else {
+ o << "the_arguments";
+ }
+ o << ")), ::SAL_NO_ACQUIRE), ::css::uno::UNO_QUERY);\n" << indent()
+ << ("::css::uno::Reference< ::css::lang::XInitialization > "
+ "init(the_instance, ::css::uno::UNO_QUERY);\n")
+ << indent() << "if (init.is()) {\n"
+ << indent() << " init->initialize(";
+ if (cons.parameters.empty()) {
+ o << "::css::uno::Sequence< ::css::uno::Any >()";
+ } else {
+ o << "the_arguments";
+ }
+ o << ");\n" << indent() << "}\n";
+ o << "#else\n"
+ << indent() << "the_instance = ::css::uno::Reference< "
+ << scopedBaseName
+ << (" >(the_context->getServiceManager()->"
+ "createInstanceWithArgumentsAndContext("
+ " \"")
+ << name_ << "\", ";
+ if (rest) {
+ o << codemaker::cpp::translateUnoToCppIdentifier(
+ u2b(cons.parameters.back().name), "param",
+ codemaker::cpp::IdentifierTranslationMode::NonGlobal);
+ } else if (cons.parameters.empty()) {
+ o << "::css::uno::Sequence< ::css::uno::Any >()";
+ } else {
+ o << "the_arguments";
+ }
+ o << ", the_context), ::css::uno::UNO_QUERY);\n#endif\n";
+ if (!tree.getRoot().present) {
+ dec();
+ o << indent()
+ << "} catch (const ::css::uno::RuntimeException &) {\n";
+ inc();
+ o << indent() << "throw;\n";
+ dec();
+ dumpCatchClauses(o, &tree.getRoot());
+ o << indent()
+ << ("} catch (const ::css::uno::Exception &"
+ " the_exception) {\n");
+ inc();
+ o << indent() << "throw ::css::uno::DeploymentException(";
+ failsToSupply(o, name_, baseName);
+ o << " + \": \" + the_exception.Message, the_context);\n";
+ dec();
+ o << indent() << "}\n";
+ }
+ o << indent() << "if (!the_instance.is()) {\n";
+ inc();
+ o << indent() << "throw ::css::uno::DeploymentException(";
+ failsToSupply(o, name_, baseName);
+ o << ", the_context);\n";
+ dec();
+ o << indent() << "}\n" << indent() << "return the_instance;\n";
+ dec();
+ o << indent() << "}\n\n";
+ }
+ }
+ }
+ o << "private:\n";
+ o << indent() << cppName << "(); // not implemented\n"
+ << indent() << cppName << "(" << cppName << " &); // not implemented\n"
+ << indent() << "~" << cppName << "(); // not implemented\n"
+ << indent() << "void operator =(" << cppName << "); // not implemented\n";
+ dec();
+ o << "};\n\n";
+ if (codemaker::cppumaker::dumpNamespaceClose(o, name_, false)) {
+ o << "\n";
+ }
+ o << "\n#endif // "<< headerDefine << "\n";
+}
+
+void ServiceType::dumpCatchClauses(
+ FileStream & out, codemaker::ExceptionTreeNode const * node)
+{
+ if (node->present) {
+ out << indent() << "} catch (const ";
+ dumpType(out, b2u(node->name));
+ out << " &) {\n";
+ inc();
+ out << indent() << "throw;\n";
+ dec();
+ } else {
+ for (std::unique_ptr<codemaker::ExceptionTreeNode> const & pChild : node->children) {
+ dumpCatchClauses(out, pChild.get());
+ }
+ }
+}
+
+class SingletonType: public ConstructiveType
+{
+public:
+ SingletonType(
+ rtl::Reference< unoidl::InterfaceBasedSingletonEntity > const & entity,
+ OUString const & name, rtl::Reference< TypeManager > const & manager):
+ ConstructiveType(name, manager), entity_(entity) {
+ assert(entity.is());
+ }
+
+private:
+ virtual void dumpHppFile(
+ FileStream & o, codemaker::cppumaker::Includes & includes) override;
+
+ rtl::Reference< unoidl::InterfaceBasedSingletonEntity > entity_;
+};
+
+void SingletonType::dumpHppFile(
+ FileStream & o, codemaker::cppumaker::Includes & includes)
+{
+ OString cppName(
+ codemaker::cpp::translateUnoToCppIdentifier(
+ u2b(id_), "singleton", isGlobal()));
+ OString baseName(u2b(entity_->getBase()));
+ OString scopedBaseName(codemaker::cpp::scopedCppName(baseName));
+ OUString headerDefine(dumpHeaderDefine(o, u"HPP"));
+ o << "\n";
+ //TODO: Decide whether the types added to includes should rather be added to
+ // m_dependencies (and thus be generated during dumpDependedTypes):
+ includes.add("com.sun.star.uno.DeploymentException");
+ includes.add("com.sun.star.uno.XComponentContext");
+ includes.addCassert();
+ includes.addAny();
+ includes.addReference();
+ includes.addRtlUstringH();
+ includes.addRtlUstringHxx();
+ includes.dump(o, nullptr, true);
+ o << ("\n#if defined ANDROID || defined IOS //TODO\n"
+ "#include <com/sun/star/lang/XInitialization.hpp>\n"
+ "#include <osl/detail/component-defines.h>\n#endif\n\n"
+ "#if defined LO_URE_CURRENT_ENV && defined LO_URE_CTOR_ENV_")
+ << name_.replaceAll(".", "_dot_")
+ << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_"
+ << name_.replaceAll(".", "_dot_") << ") && defined LO_URE_CTOR_FUN_"
+ << name_.replaceAll(".", "_dot_")
+ << "\nextern \"C\" ::css::uno::XInterface * SAL_CALL LO_URE_CTOR_FUN_"
+ << name_.replaceAll(".", "_dot_")
+ << "(::css::uno::XComponentContext *, ::css::uno::Sequence< "
+ "::css::uno::Any > const &);\n#endif\n";
+ o << "\n";
+ if (codemaker::cppumaker::dumpNamespaceOpen(o, name_, false)) {
+ o << "\n";
+ }
+ o << "\nclass " << cppName << " {\npublic:\n";
+ inc();
+ o << indent() << "static ::css::uno::Reference< "
+ << scopedBaseName << " > "
+ << codemaker::cpp::translateUnoToCppIdentifier(
+ "get", "method", codemaker::cpp::IdentifierTranslationMode::NonGlobal, &cppName)
+ << ("(::css::uno::Reference<"
+ " ::css::uno::XComponentContext > const & the_context)"
+ " {\n");
+ inc();
+ o << indent() << "assert(the_context.is());\n" << indent()
+ << "::css::uno::Reference< " << scopedBaseName
+ << (" > instance;\n#if defined LO_URE_CURRENT_ENV && defined "
+ "LO_URE_CTOR_ENV_")
+ << name_.replaceAll(".", "_dot_")
+ << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_"
+ << name_.replaceAll(".", "_dot_")
+ << ") && defined LO_URE_CTOR_FUN_"
+ << name_.replaceAll(".", "_dot_") << "\n" << indent()
+ << "instance = ::css::uno::Reference< " << scopedBaseName
+ << (" >(::css::uno::Reference< ::css::uno::XInterface >("
+ "static_cast< ::css::uno::XInterface * >((*"
+ "LO_URE_CTOR_FUN_")
+ << name_.replaceAll(".", "_dot_")
+ << (")(the_context.get(), ::css::uno::Sequence<"
+ " ::css::uno::Any >())), ::SAL_NO_ACQUIRE),"
+ " ::css::uno::UNO_QUERY);\n#else\n")
+ << indent() << ("the_context->getValueByName("
+ "::rtl::OUString( \"/singletons/")
+ << name_ << "\" )) >>= instance;\n#endif\n"
+ << indent() << "if (!instance.is()) {\n";
+ inc();
+ o << indent()
+ << ("throw ::css::uno::DeploymentException("
+ "::rtl::OUString( \"component context"
+ " fails to supply singleton ")
+ << name_ << " of type " << baseName << "\" ), the_context);\n";
+ dec();
+ o << indent() << "}\n" << indent() << "return instance;\n";
+ dec();
+ o << indent() << "}\n\n";
+ o << "private:\n";
+ o << indent() << cppName << "(); // not implemented\n"
+ << indent() << cppName << "(" << cppName << " &); // not implemented\n"
+ << indent() << "~" << cppName << "(); // not implemented\n"
+ << indent() << "void operator =(" << cppName << "); // not implemented\n";
+ dec();
+ o << "};\n\n";
+ if (codemaker::cppumaker::dumpNamespaceClose(o, name_, false)) {
+ o << "\n";
+ }
+ o << "\n#endif // "<< headerDefine << "\n";
+}
+
+}
+
+void produce(
+ OUString const & name, rtl::Reference< TypeManager > const & manager,
+ codemaker::GeneratedTypeSet & generated, CppuOptions const & options)
+{
+ if (generated.contains(u2b(name))) {
+ return;
+ }
+ generated.add(u2b(name));
+ if (!manager->foundAtPrimaryProvider(name)) {
+ return;
+ }
+ rtl::Reference< unoidl::Entity > ent;
+ rtl::Reference< unoidl::MapCursor > cur;
+ switch (manager->getSort(name, &ent, &cur)) {
+ case codemaker::UnoType::Sort::Module: {
+ OUString prefix;
+ if (!name.isEmpty()) {
+ prefix = name + ".";
+ }
+ for (;;) {
+ OUString mem;
+ if (!cur->getNext(&mem).is()) {
+ break;
+ }
+ produce(prefix + mem, manager, generated, options);
+ }
+ break;
+ }
+ case codemaker::UnoType::Sort::Enum: {
+ EnumType t(
+ dynamic_cast< unoidl::EnumTypeEntity * >(ent.get()), name,
+ manager);
+ t.dump(options);
+ t.dumpDependedTypes(generated, options);
+ break;
+ }
+ case codemaker::UnoType::Sort::PlainStruct: {
+ PlainStructType t(
+ dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get()),
+ name, manager);
+ t.dump(options);
+ t.dumpDependedTypes(generated, options);
+ break;
+ }
+ case codemaker::UnoType::Sort::PolymorphicStructTemplate: {
+ PolyStructType t(
+ dynamic_cast< unoidl::PolymorphicStructTypeTemplateEntity * >(
+ ent.get()),
+ name, manager);
+ t.dump(options);
+ t.dumpDependedTypes(generated, options);
+ break;
+ }
+ case codemaker::UnoType::Sort::Exception: {
+ ExceptionType t(
+ dynamic_cast< unoidl::ExceptionTypeEntity * >(ent.get()), name,
+ manager);
+ t.dump(options);
+ t.dumpDependedTypes(generated, options);
+ break;
+ }
+ case codemaker::UnoType::Sort::Interface: {
+ InterfaceType t(
+ dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get()), name,
+ manager);
+ t.dump(options);
+ t.dumpDependedTypes(generated, options);
+ break;
+ }
+ case codemaker::UnoType::Sort::Typedef: {
+ Typedef t(
+ dynamic_cast< unoidl::TypedefEntity * >(ent.get()), name,
+ manager);
+ t.dump(options);
+ t.dumpDependedTypes(generated, options);
+ break;
+ }
+ case codemaker::UnoType::Sort::ConstantGroup: {
+ ConstantGroup t(
+ dynamic_cast< unoidl::ConstantGroupEntity * >(ent.get()), name,
+ manager);
+ if (t.hasConstants()) {
+ t.dump(options);
+ }
+ break;
+ }
+ case codemaker::UnoType::Sort::SingleInterfaceBasedService: {
+ ServiceType t(
+ dynamic_cast< unoidl::SingleInterfaceBasedServiceEntity * >(
+ ent.get()),
+ name, manager);
+ t.dump(options);
+ t.dumpDependedTypes(generated, options);
+ break;
+ }
+ case codemaker::UnoType::Sort::InterfaceBasedSingleton: {
+ SingletonType t(
+ dynamic_cast< unoidl::InterfaceBasedSingletonEntity * >(
+ ent.get()),
+ name, manager);
+ t.dump(options);
+ t.dumpDependedTypes(generated, options);
+ break;
+ }
+ case codemaker::UnoType::Sort::AccumulationBasedService:
+ case codemaker::UnoType::Sort::ServiceBasedSingleton:
+ break;
+ default:
+ throw CannotDumpException(
+ "unexpected entity \"" + name + "\" in call to produce");
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */