/* -*- 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
{
using FileType = codemaker::cppumaker::FileType;
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);
}
OString getFileExtension(FileType eFileType)
{
switch(eFileType)
{
default:
case FileType::HDL: return ".hdl"_ostr;
case FileType::HPP: return ".hpp"_ostr;
}
}
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, FileType eFileType,
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_, FileType::HDL, options);
dumpFile(uri, name_, FileType::HPP, 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"_ostr))
m_cppuTypeLeak = true;
if (options.isValid("-C"_ostr) || options.isValid("-CS"_ostr))
m_cppuTypeDynamic = false;
}
dumpFiles(
options.isValid("-O"_ostr) ? b2u(options.getOption("-O"_ostr)) : u""_ustr, options);
}
void CppuType::dumpFile(
std::u16string_view uri, std::u16string_view name, FileType eFileType,
CppuOptions const & options)
{
OUString fileUri(
b2u(createFileNameFromType(
u2b(uri), u2b(name), getFileExtension(eFileType))));
if (fileUri.isEmpty()) {
throw CannotDumpException(OUString::Concat("empty target URI for entity ") + name);
}
bool exists = fileExists(u2b(fileUri));
if (exists && options.isValid("-G"_ostr)) {
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, eFileType);
try {
switch(eFileType)
{
case FileType::HPP:
addGetCppuTypeIncludes(includes);
dumpHppFile(out, includes);
break;
case FileType::HDL:
dumpHdlFile(out, includes);
break;
}
} 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"_ostr));
}
void CppuType::dumpDependedTypes(
codemaker::GeneratedTypeSet & generated, CppuOptions const & options) const
{
if (!options.isValid("-nD"_ostr)) {
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
? u"typelib_TypeClass_VOID"_ustr
: u"::css::uno::TypeClass_VOID"_ustr;
case codemaker::UnoType::Sort::Boolean:
return cStyle
? u"typelib_TypeClass_BOOLEAN"_ustr
: u"::css::uno::TypeClass_BOOLEAN"_ustr;
case codemaker::UnoType::Sort::Byte:
return cStyle
? u"typelib_TypeClass_BYTE"_ustr
: u"::css::uno::TypeClass_BYTE"_ustr;
case codemaker::UnoType::Sort::Short:
return cStyle
? u"typelib_TypeClass_SHORT"_ustr
: u"::css::uno::TypeClass_SHORT"_ustr;
case codemaker::UnoType::Sort::UnsignedShort:
return cStyle
? u"typelib_TypeClass_UNSIGNED_SHORT"_ustr
: u"::css::uno::TypeClass_UNSIGNED_SHORT"_ustr;
case codemaker::UnoType::Sort::Long:
return cStyle
? u"typelib_TypeClass_LONG"_ustr
: u"::css::uno::TypeClass_LONG"_ustr;
case codemaker::UnoType::Sort::UnsignedLong:
return cStyle
? u"typelib_TypeClass_UNSIGNED_LONG"_ustr
: u"::css::uno::TypeClass_UNSIGNED_LONG"_ustr;
case codemaker::UnoType::Sort::Hyper:
return cStyle
? u"typelib_TypeClass_HYPER"_ustr
: u"::css::uno::TypeClass_HYPER"_ustr;
case codemaker::UnoType::Sort::UnsignedHyper:
return cStyle
? u"typelib_TypeClass_UNSIGNED_HYPER"_ustr
: u"::css::uno::TypeClass_UNSIGNED_HYPER"_ustr;
case codemaker::UnoType::Sort::Float:
return cStyle
? u"typelib_TypeClass_FLOAT"_ustr
: u"::css::uno::TypeClass_FLOAT"_ustr;
case codemaker::UnoType::Sort::Double:
return cStyle
? u"typelib_TypeClass_DOUBLE"_ustr
: u"::css::uno::TypeClass_DOUBLE"_ustr;
case codemaker::UnoType::Sort::Char:
return cStyle
? u"typelib_TypeClass_CHAR"_ustr
: u"::css::uno::TypeClass_CHAR"_ustr;
case codemaker::UnoType::Sort::String:
return cStyle
? u"typelib_TypeClass_STRING"_ustr
: u"::css::uno::TypeClass_STRING"_ustr;
case codemaker::UnoType::Sort::Type:
return cStyle
? u"typelib_TypeClass_TYPE"_ustr
: u"::css::uno::TypeClass_TYPE"_ustr;
case codemaker::UnoType::Sort::Any:
return cStyle
? u"typelib_TypeClass_ANY"_ustr
: u"::css::uno::TypeClass_ANY"_ustr;
case codemaker::UnoType::Sort::Sequence:
return cStyle
? u"typelib_TypeClass_SEQUENCE"_ustr
: u"::css::uno::TypeClass_SEQUENCE"_ustr;
case codemaker::UnoType::Sort::Enum:
return cStyle
? u"typelib_TypeClass_ENUM"_ustr
: u"::css::uno::TypeClass_ENUM"_ustr;
case codemaker::UnoType::Sort::PlainStruct:
case codemaker::UnoType::Sort::PolymorphicStructTemplate:
case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
return cStyle
? u"typelib_TypeClass_STRUCT"_ustr
: u"::css::uno::TypeClass_STRUCT"_ustr;
case codemaker::UnoType::Sort::Exception:
return cStyle
? u"typelib_TypeClass_EXCEPTION"_ustr
: u"::css::uno::TypeClass_EXCEPTION"_ustr;
case codemaker::UnoType::Sort::Interface:
return cStyle
? u"typelib_TypeClass_INTERFACE"_ustr
: u"::css::uno::TypeClass_INTERFACE"_ustr;
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#if defined LIBO_INTERNAL_ONLY\n#include <type_traits>\n#endif\n\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#if defined LIBO_INTERNAL_ONLY\nnamespace cppu::detail {\n";
if (name_ == "com.sun.star.uno.XInterface") {
out << "template<typename> struct IsUnoInterfaceType: ::std::false_type {};\n"
"template<typename T> inline constexpr auto isUnoInterfaceType ="
" sizeof (T) && IsUnoInterfaceType<T>::value;\n";
}
out << "template<> struct IsUnoInterfaceType<";
dumpType(out, name_, false, false, true);
out << ">: ::std::true_type {};\n}\n#endif\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(u"com.sun.star.uno.RuntimeException"_ustr);
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"_ostr);
}
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 << " "
<< codemaker::cpp::translateUnoToCppIdentifier(
u2b(member.name), "constant",
codemaker::cpp::IdentifierTranslationMode::KeywordsOnly)
<< " = ";
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<const " << codemaker::cpp::scopedCppName(u2b(base))
<< "&>(the_lhs), static_cast<const " << 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();) {
const auto iter = types.find(i->type);
assert(iter != types.end());
out << indent() << "{ { " << getTypeClass(i->type, true)
<< ", the_tname" << iter->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) {
const auto iter = parameters.find(i->type);
assert(iter != parameters.end());
sal_uInt32 k = iter->second;
out << "the_pclass" << k << ", the_pname" << k << ".pData";
} else {
const auto iter = types.find(i->type);
assert(iter != types.end());
out << getTypeClass(i->type, true) << ", the_tname"
<< iter->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")
{
includes.addCustom(u"#if defined(LIBO_INTERNAL_ONLY) && !defined(NDEBUG)"_ustr);
includes.addCustom(u"#if __has_include(<version>)"_ustr);
includes.addCustom(u"#include <version>"_ustr);
includes.addCustom(u"#endif"_ustr);
includes.addCustom(u"#if defined(__cpp_lib_source_location) && __cpp_lib_source_location >= 201907"_ustr);
includes.addCustom(u"#include <source_location>"_ustr);
includes.addCustom(u"#define LIBO_USE_SOURCE_LOCATION std"_ustr);
includes.addCustom(u"#elif __has_include(<experimental/source_location>)"_ustr);
includes.addCustom(u"#include <experimental/source_location>"_ustr);
includes.addCustom(u"#define LIBO_USE_SOURCE_LOCATION std::experimental"_ustr);
includes.addCustom(u"#endif"_ustr);
includes.addCustom(u"#endif"_ustr);
includes.addCustom(u"#if defined LIBO_USE_SOURCE_LOCATION"_ustr);
includes.addCustom(u"#include <o3tl/runtimetooustring.hxx>"_ustr);
includes.addCustom(u"#endif"_ustr);
}
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 << " LIBO_USE_SOURCE_LOCATION::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 ? "" : ", ") << "LIBO_USE_SOURCE_LOCATION::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 << " LIBO_USE_SOURCE_LOCATION::source_location location = LIBO_USE_SOURCE_LOCATION::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 << ", LIBO_USE_SOURCE_LOCATION::source_location location = LIBO_USE_SOURCE_LOCATION::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 << "\n#if defined __GNUC__\n"; // gcc does not like visibility annotation on enum
o << "\nenum class " << id_ << "\n{\n";
o << "\n#else\n";
o << "\nenum class SAL_DLLPUBLIC_RTTI " << id_ << "\n{\n";
o << "\n#endif\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_, FileType::HPP, 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"_ostr);
includes.add("com.sun.star.uno.XComponentContext"_ostr);
for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor& cons : entity_->getConstructors()) {
if (cons.defaultConstructor) {
includes.add("com.sun.star.uno.Exception"_ostr);
includes.add("com.sun.star.uno.RuntimeException"_ostr);
} 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"_ostr);
includes.add("com.sun.star.uno.RuntimeException"_ostr);
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"_ostr, "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"_ostr);
includes.add("com.sun.star.uno.XComponentContext"_ostr);
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"_ostr, "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: */
↑ V530 The return value of function 'dumpHeaderDefine' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'replace' is required to be utilized.
↑ V530 The return value of function 'replace' is required to be utilized.
↑ V530 The return value of function 'replace' is required to be utilized.
↑ V530 The return value of function 'replace' is required to be utilized.
↑ V530 The return value of function 'replace' is required to be utilized.