/* -*- 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 #include #include #include #include #include #include "registry/reader.hxx" #include "rtl/alloc.h" #include "rtl/ustring.hxx" #include "rtl/strbuf.hxx" #include "codemaker/dependencies.hxx" #include "codemaker/exceptiontree.hxx" #include "codemaker/generatedtypeset.hxx" #include "codemaker/unotype.hxx" #include "cpputype.hxx" #include "cppuoptions.hxx" #include "dumputils.hxx" #include "includes.hxx" using namespace codemaker::cpp; using ::rtl::OUString; using ::rtl::OString; using ::rtl::OStringBuffer; namespace { rtl::OString translateSimpleUnoType(rtl::OString const & unoType, bool cppuUnoType=false) { static rtl::OString const trans[codemaker::UnoType::SORT_COMPLEX + 1] = { "void", "::sal_Bool", "::sal_Int8", "::sal_Int16", "::sal_uInt16", "::sal_Int32", "::sal_uInt32", "::sal_Int64", "::sal_uInt64", "float", "double", "::sal_Unicode", "::rtl::OUString", "::com::sun::star::uno::Type", "::com::sun::star::uno::Any", rtl::OString() }; const codemaker::UnoType::Sort sort = codemaker::UnoType::getSort(unoType); if (cppuUnoType && (sort == codemaker::UnoType::SORT_UNSIGNED_SHORT || sort == codemaker::UnoType::SORT_CHAR) ) { if (sort == codemaker::UnoType::SORT_CHAR) return "::cppu::UnoCharType"; else return "::cppu::UnoUnsignedShortType"; } return trans[sort]; } bool isBootstrapType(rtl::OString const & name) { static char const * const names[] = { "com/sun/star/beans/PropertyAttribute", "com/sun/star/beans/PropertyValue", "com/sun/star/beans/XFastPropertySet", "com/sun/star/beans/XMultiPropertySet", "com/sun/star/beans/XPropertyAccess", "com/sun/star/beans/XPropertySet", "com/sun/star/beans/XPropertySetOption", "com/sun/star/bridge/UnoUrlResolver", "com/sun/star/bridge/XUnoUrlResolver", "com/sun/star/connection/SocketPermission", "com/sun/star/container/XElementAccess", "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/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/XArrayTypeDescription", "com/sun/star/reflection/XCompoundTypeDescription", "com/sun/star/reflection/XEnumTypeDescription", "com/sun/star/reflection/XIdlClass", "com/sun/star/reflection/XIdlField2", "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/XTypeDescriptionEnumerationAccess", "com/sun/star/reflection/XUnionTypeDescription", "com/sun/star/registry/XImplementationRegistration", "com/sun/star/registry/XRegistryKey", "com/sun/star/registry/XSimpleRegistry", "com/sun/star/security/RuntimePermission", "com/sun/star/security/XAccessController", "com/sun/star/uno/DeploymentException", "com/sun/star/uno/RuntimeException", "com/sun/star/uno/XAggregation", "com/sun/star/uno/XComponentContext", "com/sun/star/uno/XCurrentContext", "com/sun/star/uno/XUnloadingPreference", "com/sun/star/uno/XWeak", "com/sun/star/util/XMacroExpander" }; // cf. cppuhelper/unotypes/Makefile UNOTYPES (plus missing dependencies) for (std::size_t i = 0; i < SAL_N_ELEMENTS(names); ++i) { if (name.equals(names[i])) { return true; } } return false; } } //************************************************************************* // CppuType //************************************************************************* CppuType::CppuType(typereg::Reader& typeReader, const OString& typeName, const TypeManager& typeMgr) : m_inheritedMemberCount(0) , m_cppuTypeLeak(false) , m_cppuTypeDynamic(true) , m_indentLength(0) , m_typeName(typeName) , m_name(typeName.copy(typeName.lastIndexOf('/') + 1)) , m_reader(typeReader) , m_typeMgr(typeMgr) , m_dependencies(typeMgr, typeName) {} CppuType::~CppuType() { } void CppuType::addGetCppuTypeIncludes(codemaker::cppumaker::Includes & includes) const { if (m_typeName.equals("com/sun/star/uno/XInterface") || m_typeName.equals("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::dumpDeclaration(FileStream &) throw (CannotDumpException) { OSL_ASSERT(false); } bool CppuType::dumpFiles(CppuOptions * options, rtl::OString const & outPath) { return dumpFile(options, ".hdl", m_typeName, outPath) && dumpFile(options, ".hpp", m_typeName, outPath); } 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::dumpTemplateHead(FileStream &) const {} void CppuType::dumpTemplateParameters(FileStream &) const {} void CppuType::dumpGetCppuTypePreamble(FileStream & out) { if (isPolymorphic()) { out << "namespace cppu {\n\n"; dumpTemplateHead(out); out << "class UnoType< "; dumpType(out, m_typeName); dumpTemplateParameters(out); out << " > {\npublic:\n"; inc(); out << indent() << "static inline ::com::sun::star::uno::Type const & get() {\n"; } else { if (codemaker::cppumaker::dumpNamespaceOpen(out, m_typeName, false)) { out << "\n\n"; } out << ("inline ::com::sun::star::uno::Type const &" " cppu_detail_getUnoType(SAL_UNUSED_PARAMETER "); dumpType(out, m_typeName, 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, m_typeName, false)) { out << "\n\n"; } } dumpTemplateHead(out); out << ("inline ::com::sun::star::uno::Type const & SAL_CALL" " getCppuType(SAL_UNUSED_PARAMETER "); dumpType(out, m_typeName); dumpTemplateParameters(out); out << " const *) SAL_THROW(()) {\n"; inc(); out << indent() << "return ::cppu::UnoType< "; dumpType(out, m_typeName); dumpTemplateParameters(out); out << " >::get();\n"; dec(); out << indent() << "}\n"; } sal_Bool CppuType::dump(CppuOptions* pOptions) throw( CannotDumpException ) { if (!m_dependencies.isValid()) { return false; } addSpecialDependencies(); if (isBootstrapType(m_typeName)) { 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 (pOptions->isValid("-L")) m_cppuTypeLeak = true; if (pOptions->isValid("-C") || pOptions->isValid("-CS")) m_cppuTypeDynamic = false; } OString outPath; if (pOptions->isValid("-O")) outPath = pOptions->getOption("-O"); return dumpFiles(pOptions, outPath); } sal_Bool CppuType::dumpFile(CppuOptions* pOptions, const OString& sExtension, const OString& sName, const OString& sOutPath ) throw( CannotDumpException ) { sal_Bool ret = sal_False; OString sTmpExt(".tml"); sal_Bool bHdl = sal_True; ; if (sExtension.equals(".hpp")) { sTmpExt = ".tmp"; bHdl = sal_False; } OString sFileName = createFileNameFromType(sOutPath, sName, sExtension); if (sFileName.isEmpty()) return sal_False; sal_Bool bFileExists = fileExists( sFileName ); sal_Bool bFileCheck = sal_False; if ( bFileExists && pOptions->isValid("-G") ) return sal_True; if ( bFileExists && pOptions->isValid("-Gc") ) bFileCheck = sal_True; OString sTmpDir = getTempDir(sFileName); FileStream oFile; oFile.createTempFile(sTmpDir); OString sTmpFileName; if(!oFile.isValid()) { OString message("cannot open "); message += sFileName + " for writing"; throw CannotDumpException(message); } else sTmpFileName = oFile.getName(); codemaker::cppumaker::Includes includes(m_typeMgr, m_dependencies, !bHdl); if (bHdl) ret = dumpHFile(oFile, includes); else { addGetCppuTypeIncludes(includes); ret = dumpHxxFile(oFile, includes); } oFile.close(); if (ret) { ret = makeValidTypeFile(sFileName, sTmpFileName, bFileCheck); } else { // remove existing type file if something goes wrong to ensure consistency if (fileExists(sFileName)) removeTypeFile(sFileName); // remove tmp file if something goes wrong removeTypeFile(sTmpFileName); } return ret; } void CppuType::dumpDependedTypes( codemaker::GeneratedTypeSet & generated, CppuOptions * options) { codemaker::Dependencies::Map const & map(m_dependencies.getMap()); for (codemaker::Dependencies::Map::const_iterator i(map.begin()); i != map.end(); ++i) { if (!produceType(i->first, m_typeMgr, generated, options)) { fprintf( stderr, "%s ERROR: cannot dump Type '%s'\n", options->getProgramName().getStr(), i->first.getStr()); exit(99); } } } OString CppuType::dumpHeaderDefine( FileStream& o, char const * prefix, sal_Bool bExtended) { if (m_typeName.equals("/")) { bExtended = sal_False; m_typeName = "global"; } sal_uInt32 length = 3 + m_typeName.getLength() + strlen(prefix); if (bExtended) length += m_name.getLength() + 1; OStringBuffer tmpBuf(length); tmpBuf.append("INCLUDED_"); tmpBuf.append(m_typeName); tmpBuf.append('_'); if (bExtended) { tmpBuf.append(m_name); tmpBuf.append('_'); } tmpBuf.append(prefix); OString tmp(tmpBuf.makeStringAndClear().replace('/', '_').toAsciiUpperCase()); o << "#ifndef " << tmp << "\n#define " << tmp << "\n"; return tmp; } void CppuType::addDefaultHIncludes(codemaker::cppumaker::Includes & includes) const { //TODO: Only include what is really needed includes.addCppuMacrosHxx(); if (m_typeMgr.getTypeClass(m_typeName) == RT_TYPE_INTERFACE) { includes.addReference(); } } void CppuType::addDefaultHxxIncludes(codemaker::cppumaker::Includes & includes) const { //TODO: Only include what is really needed includes.addRtlInstanceHxx(); includes.addOslMutexHxx(); includes.addType(); if (m_typeMgr.getTypeClass(m_typeName) == RT_TYPE_INTERFACE) { includes.addReference(); } } void CppuType::dumpInitializer( FileStream & out, bool parameterized, rtl::OUString const & type) const { out << "("; if (!parameterized) { for (rtl::OString t( rtl::OUStringToOString(type, RTL_TEXTENCODING_UTF8));;) { sal_Int32 rank; std::vector< rtl::OString > args; t = codemaker::UnoType::decompose(t, &rank, &args); if (rank == 0) { switch (codemaker::UnoType::getSort(t)) { case codemaker::UnoType::SORT_BOOLEAN: out << "false"; break; case codemaker::UnoType::SORT_BYTE: case codemaker::UnoType::SORT_SHORT: case codemaker::UnoType::SORT_UNSIGNED_SHORT: case codemaker::UnoType::SORT_LONG: case codemaker::UnoType::SORT_UNSIGNED_LONG: case codemaker::UnoType::SORT_HYPER: case codemaker::UnoType::SORT_UNSIGNED_HYPER: case codemaker::UnoType::SORT_FLOAT: case codemaker::UnoType::SORT_DOUBLE: case codemaker::UnoType::SORT_CHAR: out << "0"; break; case codemaker::UnoType::SORT_COMPLEX: switch (m_typeMgr.getTypeClass(t)) { case RT_TYPE_ENUM: { typereg::Reader reader(m_typeMgr.getTypeReader(t)); OSL_ASSERT(reader.isValid()); out << scopedCppName(t) << "_" << rtl::OUStringToOString( reader.getFieldName(0), RTL_TEXTENCODING_UTF8); break; } case RT_TYPE_TYPEDEF: t = resolveTypedefs(t); continue; default: break; } break; default: break; } } break; } } out << ")"; } void CppuType::dumpHFileContent( FileStream & out, codemaker::cppumaker::Includes & includes) { addDefaultHIncludes(includes); dumpHeaderDefine(out, "HDL"); out << "\n"; includes.dump(out, 0); out << ("\nnamespace com { namespace sun { namespace star { namespace uno" " { class Type; } } } }\n\n"); if (codemaker::cppumaker::dumpNamespaceOpen(out, m_typeName, false)) { out << "\n"; } dumpDeclaration(out); if (!(m_typeName.equalsL( RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/XInterface")) || m_typeName.equalsL( RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Exception")) || isPolymorphic())) { out << "\n" << indent() << ("inline ::com::sun::star::uno::Type const &" " cppu_detail_getUnoType(SAL_UNUSED_PARAMETER "); dumpType(out, m_typeName, false, false, true); out << " const *);\n"; } if (codemaker::cppumaker::dumpNamespaceClose(out, m_typeName, false)) { out << "\n"; } out << "\n"; dumpTemplateHead(out); out << "inline ::com::sun::star::uno::Type const & SAL_CALL getCppuType("; dumpType(out, m_typeName, true); dumpTemplateParameters(out); out << " *) SAL_THROW(());\n\n#endif\n"; } void CppuType::dumpGetCppuType(FileStream & out) { if (m_typeName.equals("com/sun/star/uno/XInterface")) { out << indent() << ("inline ::com::sun::star::uno::Type const & SAL_CALL" " getCppuType(SAL_UNUSED_PARAMETER "); dumpType(out, m_typeName, true, false); out << " *) SAL_THROW(()) {\n"; inc(); out << indent() << ("return ::cppu::UnoType< ::com::sun::star::uno::XInterface" " >::get();\n"); dec(); out << indent() << "}\n"; } else if (m_typeName.equals("com/sun/star/uno/Exception")) { out << indent() << ("inline ::com::sun::star::uno::Type const & SAL_CALL" " getCppuType(SAL_UNUSED_PARAMETER "); dumpType(out, m_typeName, true, false); out << " *) SAL_THROW(()) {\n"; inc(); out << indent() << ("return ::cppu::UnoType< ::com::sun::star::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& 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_type_init( &the_type, " << getTypeClass(m_typeName, sal_True) << ", \"" << m_typeName.replace('/', '.') << "\" );\n"; dec(); o << indent() << "}\n"; o << indent() << ("return * reinterpret_cast< ::com::sun::star::uno::Type * >(" " &the_type );\n"); dumpGetCppuTypePostamble(o); } void CppuType::dumpNormalGetCppuType(FileStream& o) { dumpGetCppuTypePreamble(o); o << indent() << "static typelib_TypeDescriptionReference * the_type = 0;\n"; o << indent() << "if ( !the_type )\n" << indent() << "{\n"; inc(); OString superType; if (m_reader.getSuperTypeCount() >= 1) { superType = rtl::OUStringToOString( m_reader.getSuperTypeName(0), RTL_TEXTENCODING_UTF8); } sal_Bool bIsBaseException = sal_False; if (!superType.isEmpty()) { if ( superType.equals("com/sun/star/uno/Exception") ) { bIsBaseException = sal_True; } else { o << indent() << "const ::com::sun::star::uno::Type& rBaseType = ::cppu::UnoType< "; dumpType(o, superType, true, false, false, true); o << " >::get();\n\n"; } } sal_uInt32 count = getMemberCount(); if (count) { o << indent() << "typelib_TypeDescriptionReference * aMemberRefs[" << count << "];\n"; sal_uInt16 fieldCount = m_reader.getFieldCount(); RTFieldAccess access = RT_ACCESS_INVALID; OString fieldType, fieldName; OString scope = m_typeName.replace('/', '.'); OString modFieldType; StringSet generatedTypeSet; StringSet::iterator findIter; for (sal_uInt16 i=0; i < fieldCount; i++) { access = m_reader.getFieldFlags(i); if (access == RT_ACCESS_CONST || access == RT_ACCESS_INVALID) continue; fieldName = rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8); fieldType = checkRealBaseType( rtl::OUStringToOString( m_reader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8), sal_True); modFieldType = typeToIdentifier(fieldType); findIter = generatedTypeSet.find(fieldType); if ( findIter == generatedTypeSet.end() ) { generatedTypeSet.insert(fieldType); o << indent() << "const ::com::sun::star::uno::Type& rMemberType_" << modFieldType/*i*/ << " = ::cppu::UnoType< "; dumpType(o, fieldType, false, false, false, true); o << " >::get();\n"; } o << indent() << "aMemberRefs[" << i << "] = rMemberType_" << modFieldType/*i*/ << ".getTypeLibType();\n"; } o << "\n"; } o << indent() << "typelib_static_compound_type_init( &the_type, " << getTypeClass(m_typeName, sal_True) << ", \"" << m_typeName.replace('/', '.') << "\", "; if ( !superType.isEmpty() || bIsBaseException ) { if ( bIsBaseException ) { o << "* ::typelib_static_type_getByTypeClass( typelib_TypeClass_EXCEPTION ), " << count << ", "; } else { o << "rBaseType.getTypeLibType(), " << count << ", "; } } else { o << "0, " << count << ", "; } if (count) { o << " aMemberRefs );\n"; } else { o << " 0 );\n"; } dec(); o << indent() << "}\n"; o << indent() << ("return * reinterpret_cast< const ::com::sun::star::uno::Type * >(" " &the_type );\n"); dumpGetCppuTypePostamble(o); } void CppuType::dumpComprehensiveGetCppuType(FileStream& o) { if (!isPolymorphic()) codemaker::cppumaker::dumpNamespaceOpen(o, m_typeName, false); else o << "namespace cppu { "; o << " namespace detail {\n\n"; OString sType = m_typeName.copy(m_typeName.lastIndexOf('/') + 1); OString sStaticTypeClass = "the" + sType + "Type"; o << indent() << "struct " << sStaticTypeClass << " : public rtl::StaticWithInit< ::com::sun::star::uno::Type *, " << sStaticTypeClass << " >\n"; o << indent() << "{\n"; inc(); o << indent() << "::com::sun::star::uno::Type * operator()() const\n"; o << indent() << "{\n"; inc(); o << indent() << "::rtl::OUString sTypeName( \"" << m_typeName.replace('/', '.') << "\" );\n\n"; o << indent() << "// Start inline typedescription generation\n" << indent() << "typelib_TypeDescription * pTD = 0;\n"; OString superType; if (m_reader.getSuperTypeCount() >= 1) { superType = rtl::OUStringToOString( m_reader.getSuperTypeName(0), RTL_TEXTENCODING_UTF8); } if (!superType.isEmpty()) { o << indent() << "const ::com::sun::star::uno::Type& rSuperType = ::cppu::UnoType< "; dumpType(o, superType, false, false, false, true); o << " >::get();\n"; } dumpCppuGetTypeMemberDecl(o, CPPUTYPEDECL_ALLTYPES); sal_uInt32 count = getMemberCount(); if (count) { o << "\n" << indent() << "typelib_CompoundMember_Init aMembers[" << count << "];\n"; sal_uInt16 fieldCount = m_reader.getFieldCount(); RTFieldAccess access = RT_ACCESS_INVALID; OString fieldType, fieldName; OString scope = m_typeName.replace('/', '.'); for (sal_uInt16 i=0; i < fieldCount; i++) { access = m_reader.getFieldFlags(i); if (access == RT_ACCESS_CONST || access == RT_ACCESS_INVALID) { continue; } fieldName = rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8); fieldType = checkRealBaseType( rtl::OUStringToOString( m_reader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8), sal_True); o << indent() << "::rtl::OUString sMemberType" << i << "( \"" << fieldType.replace('/', '.') << "\" );\n"; o << indent() << "::rtl::OUString sMemberName" << i << "( \""; o << fieldName << "\" );\n"; o << indent() << "aMembers[" << i << "].eTypeClass = " << "(typelib_TypeClass)" << getTypeClass(fieldType) << ";\n" << indent() << "aMembers[" << i << "].pTypeName = sMemberType" << i << ".pData;\n" << indent() << "aMembers[" << i << "].pMemberName = sMemberName" << i << ".pData;\n"; } } o << "\n" << indent() << "typelib_typedescription_new(\n"; inc(); o << indent() << "&pTD,\n" << indent() << "(typelib_TypeClass)" << getTypeClass() << ", sTypeName.pData,\n"; if (!superType.isEmpty()) { o << indent() << "rSuperType.getTypeLibType(),\n"; } else { o << indent() << "0,\n"; } if ( count ) { o << indent() << count << ",\n" << indent() << "aMembers );\n\n"; } else { o << indent() << count << ",\n" << indent() << "0 );\n\n"; } dec(); o << indent() << ("typelib_typedescription_register( (typelib_TypeDescription**)&pTD" " );\n\n"); o << indent() << "typelib_typedescription_release( pTD );\n" << indent() << "// End inline typedescription generation\n\n"; o << indent() << "return new ::com::sun::star::uno::Type( " << getTypeClass(m_typeName) << ", sTypeName ); // leaked\n"; dec(); o << indent() << "}\n"; dec(); o << indent() << "};\n\n"; if (!isPolymorphic()) codemaker::cppumaker::dumpNamespaceClose(o, m_typeName, false); else o << " }"; o << " }\n\n"; dumpGetCppuTypePreamble(o); o << indent() << "return *detail::" << sStaticTypeClass << "::get();\n"; dumpGetCppuTypePostamble(o); } void CppuType::dumpCppuGetTypeMemberDecl(FileStream& o, CppuTypeDecl eDeclFlag) { sal_uInt16 fieldCount = m_reader.getFieldCount(); RTFieldAccess access = RT_ACCESS_INVALID; StringSet aFinishedTypes; for (sal_uInt16 i=0; i < fieldCount; i++) { access = m_reader.getFieldFlags(i); if (access == RT_ACCESS_CONST || access == RT_ACCESS_INVALID || (access & RT_ACCESS_PARAMETERIZED_TYPE) != 0) continue; rtl::OString typeName( rtl::OUStringToOString( m_reader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8)); if (aFinishedTypes.count(typeName) == 0) { aFinishedTypes.insert(typeName); dumpCppuGetType(o, typeName, sal_True, eDeclFlag); } } } IdentifierTranslationMode CppuType::isGlobal() const { if ( m_typeName.indexOf('/') < 0 ) return ITM_GLOBAL; else return ITM_NONGLOBAL; } sal_uInt32 CppuType::getMemberCount() { sal_uInt16 count = m_reader.getMethodCount(); sal_uInt16 fieldCount = m_reader.getFieldCount(); RTFieldAccess access = RT_ACCESS_INVALID; for (sal_uInt16 i=0; i < fieldCount; i++) { access = m_reader.getFieldFlags(i); if (access != RT_ACCESS_CONST && access != RT_ACCESS_INVALID) count++; } return count; } sal_uInt32 CppuType::checkInheritedMemberCount(const typereg::Reader* pReader) { sal_Bool bSelfCheck = sal_True; if (!pReader) { bSelfCheck = sal_False; pReader = &m_reader; } sal_uInt32 count = 0; OString superType; if (pReader->getSuperTypeCount() >= 1) { superType = rtl::OUStringToOString( pReader->getSuperTypeName(0), RTL_TEXTENCODING_UTF8); } if (!superType.isEmpty()) { typereg::Reader aSuperReader(m_typeMgr.getTypeReader(superType)); if ( aSuperReader.isValid() ) { count = checkInheritedMemberCount(&aSuperReader); } } if (bSelfCheck) { count += pReader->getMethodCount(); sal_uInt16 fieldCount = pReader->getFieldCount(); RTFieldAccess access = RT_ACCESS_INVALID; for (sal_uInt16 i=0; i < fieldCount; i++) { access = pReader->getFieldFlags(i); if (access != RT_ACCESS_CONST && access != RT_ACCESS_INVALID) { count++; } } } return count; } sal_uInt32 CppuType::getInheritedMemberCount() { if (m_inheritedMemberCount == 0) { m_inheritedMemberCount = checkInheritedMemberCount(0); } return m_inheritedMemberCount; } OString CppuType::getTypeClass(const OString& type, sal_Bool bCStyle) { OString typeName = (!type.isEmpty() ? type : m_typeName); RTTypeClass rtTypeClass = RT_TYPE_INVALID; if (!type.isEmpty()) { typeName = type; rtTypeClass = m_typeMgr.getTypeClass(typeName); } else { typeName = m_typeName; rtTypeClass = m_reader.getTypeClass(); } if (codemaker::UnoType::isSequenceType(typeName)) return bCStyle ? "typelib_TypeClass_SEQUENCE" : "::com::sun::star::uno::TypeClass_SEQUENCE"; switch (rtTypeClass) { case RT_TYPE_INTERFACE: return bCStyle ? "typelib_TypeClass_INTERFACE" : "::com::sun::star::uno::TypeClass_INTERFACE"; case RT_TYPE_MODULE: return bCStyle ? "typelib_TypeClass_MODULE" : "::com::sun::star::uno::TypeClass_MODULE"; case RT_TYPE_STRUCT: return bCStyle ? "typelib_TypeClass_STRUCT" : "::com::sun::star::uno::TypeClass_STRUCT"; case RT_TYPE_ENUM: return bCStyle ? "typelib_TypeClass_ENUM" : "::com::sun::star::uno::TypeClass_ENUM"; case RT_TYPE_EXCEPTION: return bCStyle ? "typelib_TypeClass_EXCEPTION" : "::com::sun::star::uno::TypeClass_EXCEPTION"; case RT_TYPE_TYPEDEF: { OString realType = checkRealBaseType( typeName ); return getTypeClass( realType, bCStyle ); } case RT_TYPE_SERVICE: return bCStyle ? "typelib_TypeClass_SERVICE" : "::com::sun::star::uno::TypeClass_SERVICE"; case RT_TYPE_INVALID: { if (type.equals("long")) return bCStyle ? "typelib_TypeClass_LONG" : "::com::sun::star::uno::TypeClass_LONG"; if (type.equals("short")) return bCStyle ? "typelib_TypeClass_SHORT" : "::com::sun::star::uno::TypeClass_SHORT"; if (type.equals("hyper")) return bCStyle ? "typelib_TypeClass_HYPER" : "::com::sun::star::uno::TypeClass_HYPER"; if (type.equals("string")) return bCStyle ? "typelib_TypeClass_STRING" : "::com::sun::star::uno::TypeClass_STRING"; if (type.equals("boolean")) return bCStyle ? "typelib_TypeClass_BOOLEAN" : "::com::sun::star::uno::TypeClass_BOOLEAN"; if (type.equals("char")) return bCStyle ? "typelib_TypeClass_CHAR" : "::com::sun::star::uno::TypeClass_CHAR"; if (type.equals("byte")) return bCStyle ? "typelib_TypeClass_BYTE" : "::com::sun::star::uno::TypeClass_BYTE"; if (type.equals("any")) return bCStyle ? "typelib_TypeClass_ANY" : "::com::sun::star::uno::TypeClass_ANY"; if (type.equals("type")) return bCStyle ? "typelib_TypeClass_TYPE" : "::com::sun::star::uno::TypeClass_TYPE"; if (type.equals("float")) return bCStyle ? "typelib_TypeClass_FLOAT" : "::com::sun::star::uno::TypeClass_FLOAT"; if (type.equals("double")) return bCStyle ? "typelib_TypeClass_DOUBLE" : "::com::sun::star::uno::TypeClass_DOUBLE"; if (type.equals("void")) return bCStyle ? "typelib_TypeClass_VOID" : "::com::sun::star::uno::TypeClass_VOID"; if (type.equals("unsigned long")) return bCStyle ? "typelib_TypeClass_UNSIGNED_LONG" : "::com::sun::star::uno::TypeClass_UNSIGNED_LONG"; if (type.equals("unsigned short")) return bCStyle ? "typelib_TypeClass_UNSIGNED_SHORT" : "::com::sun::star::uno::TypeClass_UNSIGNED_SHORT"; if (type.equals("unsigned hyper")) return bCStyle ? "typelib_TypeClass_UNSIGNED_HYPER" : "::com::sun::star::uno::TypeClass_UNSIGNED_HYPER"; } break; default: OSL_ASSERT(false); break; } return bCStyle ? "typelib_TypeClass_UNKNOWN" : "::com::sun::star::uno::TypeClass_UNKNOWN"; } void CppuType::dumpType(FileStream& o, const OString& type, bool bConst, bool bRef, bool bNative, bool cppuUnoType) const throw( CannotDumpException ) { sal_Int32 seqNum; std::vector< rtl::OString > args; rtl::OString relType( codemaker::UnoType::decompose( checkRealBaseType(type, true), &seqNum, &args)); RTTypeClass typeClass = m_typeMgr.getTypeClass(relType); if (bConst) o << "const "; {for (sal_Int32 i = 0; i < seqNum; ++i) { if (cppuUnoType) o << "::cppu::UnoSequenceType< "; else o << "::com::sun::star::uno::Sequence< "; }} switch (typeClass) { case RT_TYPE_INTERFACE: if (bNative) o << scopedCppName(relType); else o << "::com::sun::star::uno::Reference< " << scopedCppName(relType) << " >"; break; case RT_TYPE_INVALID: { OString tmp(translateSimpleUnoType(relType, cppuUnoType)); if (!tmp.isEmpty()) { o << tmp; } else throw CannotDumpException("Unknown type '" + relType + "', incomplete type library."); } break; case RT_TYPE_STRUCT: case RT_TYPE_ENUM: case RT_TYPE_TYPEDEF: case RT_TYPE_EXCEPTION: { o << scopedCppName(relType); if (!args.empty()) { o << "< "; for (std::vector< rtl::OString >::iterator i(args.begin()); i != args.end(); ++i) { if (i != args.begin()) { o << ", "; } dumpType(o, *i); } o << " >"; } break; } default: OSL_ASSERT(false); break; } {for (sal_Int32 i = 0; i < seqNum; ++i) { o << " >"; }} if (bRef) o << "&"; } void CppuType::dumpCppuGetType(FileStream& o, const OString& type, sal_Bool bDecl, CppuTypeDecl eDeclFlag) { rtl::OString relType( codemaker::UnoType::decompose(checkRealBaseType(type, true))); if (eDeclFlag == CPPUTYPEDECL_ONLYINTERFACES) { if (m_typeMgr.getTypeClass(relType) == RT_TYPE_INTERFACE) { o << indent() << "::cppu::UnoType< "; dumpType(o, type, false, false, false, true); o << " >::get()"; if (bDecl) o << ";\n"; } } else { if (codemaker::UnoType::getSort(type) != codemaker::UnoType::SORT_COMPLEX) { return; } else { if (eDeclFlag == CPPUTYPEDECL_NOINTERFACES && m_typeMgr.getTypeClass(relType) == RT_TYPE_INTERFACE) return; o << indent() << "::cppu::UnoType< "; dumpType(o, type, false, false, false, true); o << " >::get()"; } if (bDecl) o << ";\n"; } } OString CppuType::typeToIdentifier(const OString& type) { sal_Int32 seqNum; rtl::OString relType(codemaker::UnoType::decompose(type, &seqNum)); OString sIdentifier; while( seqNum > 0 ) { sIdentifier += OString("seq"); if ( --seqNum == 0 ) { sIdentifier += OString("_"); } } sIdentifier += relType.replace( ((codemaker::UnoType::getSort(relType) == codemaker::UnoType::SORT_COMPLEX) ? '/' : ' '), '_'); // TODO: find better solution to create an identifier sIdentifier = sIdentifier.replace('<', '_'); sIdentifier = sIdentifier.replace('>', '_'); sIdentifier = sIdentifier.replace(',', '_'); return sIdentifier; } bool CppuType::passByReference(rtl::OString const & unoType) { rtl::OString type(resolveTypedefs(unoType)); switch (codemaker::UnoType::getSort(type)) { default: return false; case codemaker::UnoType::SORT_STRING: case codemaker::UnoType::SORT_TYPE: case codemaker::UnoType::SORT_ANY: return true; case codemaker::UnoType::SORT_COMPLEX: return m_typeMgr.getTypeClass(type) != RT_TYPE_ENUM; } } OString CppuType::resolveTypedefs(const OString& type) const { OString baseType(type); RegistryKey key; RTTypeClass typeClass; sal_Bool isTypeDef = (m_typeMgr.getTypeClass(baseType) == RT_TYPE_TYPEDEF); typereg::Reader reader; while (isTypeDef) { reader = m_typeMgr.getTypeReader(baseType); if (reader.isValid()) { typeClass = reader.getTypeClass(); if (typeClass == RT_TYPE_TYPEDEF) baseType = rtl::OUStringToOString( reader.getSuperTypeName(0), RTL_TEXTENCODING_UTF8); else isTypeDef = sal_False; } else { break; } } return baseType; } OString CppuType::checkRealBaseType(const OString& type, sal_Bool bResolveTypeOnly) const { sal_Int32 rank; rtl::OString baseType(codemaker::UnoType::decompose(type, &rank)); RegistryKey key; RTTypeClass typeClass; sal_Bool mustBeChecked = (m_typeMgr.getTypeClass(baseType) == RT_TYPE_TYPEDEF); typereg::Reader reader; while (mustBeChecked) { reader = m_typeMgr.getTypeReader(baseType); if (reader.isValid()) { typeClass = reader.getTypeClass(); if (typeClass == RT_TYPE_TYPEDEF) { sal_Int32 n; baseType = codemaker::UnoType::decompose( rtl::OUStringToOString( reader.getSuperTypeName(0), RTL_TEXTENCODING_UTF8), &n); OSL_ASSERT(n <= SAL_MAX_INT32 - rank); //TODO rank += n; } else mustBeChecked = sal_False; } else { break; } } if (bResolveTypeOnly) { rtl::OStringBuffer buf; for (sal_Int32 i = 0; i < rank; ++i) { buf.append(RTL_CONSTASCII_STRINGPARAM("[]")); } baseType = buf.makeStringAndClear() + baseType; } return baseType; } void CppuType::dumpConstantValue(FileStream& o, sal_uInt16 index) { RTConstValue constValue = m_reader.getFieldValue(index); switch (constValue.m_type) { case RT_TYPE_NONE: break; case RT_TYPE_BOOL: if (constValue.m_value.aBool) o << "sal_True"; else o << "sal_False"; break; case RT_TYPE_BYTE: o << "(sal_Int8)" << constValue.m_value.aByte; break; case RT_TYPE_INT16: o << "(sal_Int16)" << constValue.m_value.aShort; break; case RT_TYPE_UINT16: o << "(sal_uInt16)" << constValue.m_value.aUShort; break; case RT_TYPE_INT32: // Avoid C++ compiler warnings about (un)signedness of literal // -2^31: if (constValue.m_value.aLong == SAL_MIN_INT32) { o << "SAL_MIN_INT32"; } else { o << "(sal_Int32)" << constValue.m_value.aLong; } break; case RT_TYPE_UINT32: o << "(sal_uInt32)" << OString::valueOf( static_cast< sal_Int64 >(constValue.m_value.aULong)).getStr() << "U"; break; case RT_TYPE_INT64: // Avoid C++ compiler warnings about (un)signedness of literal // -2^63: if (constValue.m_value.aHyper == SAL_MIN_INT64) { o << "SAL_MIN_INT64"; } else { ::rtl::OString tmp(OString::valueOf(constValue.m_value.aHyper)); o << "(sal_Int64) SAL_CONST_INT64(" << tmp.getStr() << ")"; } break; case RT_TYPE_UINT64: { o << "SAL_CONST_UINT64("; sal_uInt64 n = constValue.m_value.aUHyper; if (n == 0) { o << "0"; } else { std::vector< char > buf; for (; n != 0; n /= 10) { buf.push_back('0' + static_cast< char >(n % 10)); } for (std::vector< char >::reverse_iterator i(buf.rbegin()); i != buf.rend(); ++i) { o << rtl::OString::valueOf(*i).getStr(); } } o << ")"; } break; case RT_TYPE_FLOAT: { ::rtl::OString tmp( OString::valueOf(constValue.m_value.aFloat) ); o << "(float)" << tmp.getStr(); } break; case RT_TYPE_DOUBLE: { ::rtl::OString tmp( OString::valueOf(constValue.m_value.aDouble) ); o << "(double)" << tmp.getStr(); } break; case RT_TYPE_STRING: { ::rtl::OUString aUStr(constValue.m_value.aString); ::rtl::OString aStr = ::rtl::OUStringToOString(aUStr, RTL_TEXTENCODING_ASCII_US); o << "::rtl::OUString( \"" << aStr.getStr() << "\" )"; } break; } } 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); } OString CppuType::indent() const { OStringBuffer tmp(m_indentLength); for (sal_Int32 i=0; i < m_indentLength; i++) { tmp.append(' '); } return tmp.makeStringAndClear(); } //************************************************************************* // InterfaceType //************************************************************************* namespace { bool isDocumentedDeprecated(OUString const & documentation) { return documentation.indexOf("@deprecated") != -1; //TODO: this check is somewhat crude } void dumpDeprecation(FileStream & o, bool deprecated) { if (deprecated) { o << "SAL_DEPRECATED_INTERNAL(\"marked @deprecated in UNOIDL\") "; } } } InterfaceType::InterfaceType(typereg::Reader& typeReader, const OString& typeName, const TypeManager& typeMgr) : CppuType(typeReader, typeName, typeMgr) { m_inheritedMemberCount = 0; m_hasAttributes = false; m_hasMethods = false; m_isDeprecated = isDocumentedDeprecated(m_reader.getDocumentation()); } InterfaceType::~InterfaceType() { } sal_Bool InterfaceType::dumpHFile( FileStream& o, codemaker::cppumaker::Includes & includes) throw( CannotDumpException ) { if (m_reader.getMethodCount() != 0) { includes.add("com/sun/star/uno/RuntimeException"); } dumpHFileContent(o, includes); return sal_True; } void InterfaceType::dumpDeclaration(FileStream& o) throw( CannotDumpException ) { o << "\nclass SAL_NO_VTABLE " << m_name; for (sal_Int16 i = 0; i < m_reader.getSuperTypeCount(); ++i) { o << (i == 0 ? " :" : ",") << " public " << scopedCppName(rtl::OUStringToOString( m_reader.getSuperTypeName(i), RTL_TEXTENCODING_UTF8)); } o << "\n{\npublic:\n"; inc(); dumpAttributes(o); dumpMethods(o); o << "\n" << indent() << ("static inline ::com::sun::star::uno::Type const & SAL_CALL" " static_type(void * = 0);\n\n"); dec(); o << "protected:\n"; inc(); o << indent() << "~" << m_name << ("() throw () {} // avoid warnings about virtual members and" " non-virtual dtor\n"); dec(); o << "};\n\n"; } sal_Bool InterfaceType::dumpHxxFile( FileStream& o, codemaker::cppumaker::Includes & includes) throw( CannotDumpException ) { OString headerDefine(dumpHeaderDefine(o, "HPP")); o << "\n"; addDefaultHxxIncludes(includes); includes.dump(o, &m_typeName); o << "\n"; dumpGetCppuType(o); o << "\n::com::sun::star::uno::Type const & " << scopedCppName(m_typeName) << "::static_type(SAL_UNUSED_PARAMETER void *) {\n"; inc(); o << indent() << "return ::getCppuType(static_cast< "; dumpType(o, m_typeName); o << " * >(0));\n"; dec(); o << "}\n"; o << "\n#endif // "<< headerDefine << "\n"; return sal_True; } void InterfaceType::dumpAttributes(FileStream& o) { sal_uInt16 fieldCount = m_reader.getFieldCount(); sal_Bool first=sal_True; RTFieldAccess access = RT_ACCESS_INVALID; OString fieldName; OString fieldType; for (sal_uInt16 i=0; i < fieldCount; i++) { access = m_reader.getFieldFlags(i); if (access == RT_ACCESS_CONST || access == RT_ACCESS_INVALID) continue; rtl::OUString name(m_reader.getFieldName(i)); fieldName = rtl::OUStringToOString(name, RTL_TEXTENCODING_UTF8); fieldType = rtl::OUStringToOString( m_reader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8); bool depr = m_isDeprecated || isDocumentedDeprecated(m_reader.getFieldDocumentation(i)); if (first) { first = sal_False; o << "\n" << indent() << "// Attributes\n"; } o << indent(); dumpDeprecation(o, depr); o << "virtual "; dumpType(o, fieldType); o << " SAL_CALL get" << fieldName << "()"; dumpAttributeExceptionSpecification(o, name, RT_MODE_ATTRIBUTE_GET); o << " = 0;\n"; if ((access & RT_ACCESS_READONLY) == 0) { bool byRef = passByReference(fieldType); o << indent(); dumpDeprecation(o, depr); o << "virtual void SAL_CALL set" << fieldName << "( "; dumpType(o, fieldType, byRef, byRef); o << " _" << fieldName.toAsciiLowerCase() << " )"; dumpAttributeExceptionSpecification(o, name, RT_MODE_ATTRIBUTE_SET); o << " = 0;\n"; } } } void InterfaceType::dumpMethods(FileStream& o) { sal_uInt16 methodCount = m_reader.getMethodCount(); sal_Bool first=sal_True; OString methodName, returnType, paramType, paramName; sal_uInt16 paramCount = 0; RTMethodMode methodMode = RT_MODE_INVALID; RTParamMode paramMode = RT_PARAM_INVALID; sal_Bool bRef = sal_False; sal_Bool bConst = sal_False; sal_Bool bWithRunTimeExcp = sal_True; for (sal_uInt16 i=0; i < methodCount; i++) { methodMode = m_reader.getMethodFlags(i); if (methodMode == RT_MODE_ATTRIBUTE_GET || methodMode == RT_MODE_ATTRIBUTE_SET) { continue; } methodName = rtl::OUStringToOString( m_reader.getMethodName(i), RTL_TEXTENCODING_UTF8); returnType = rtl::OUStringToOString( m_reader.getMethodReturnTypeName(i), RTL_TEXTENCODING_UTF8); paramCount = m_reader.getMethodParameterCount(i); if ( methodName.equals("acquire") || methodName.equals("release") ) { bWithRunTimeExcp = sal_False; } if (first) { first = sal_False; o << "\n" << indent() << "// Methods\n"; } o << indent(); dumpDeprecation( o, (m_isDeprecated || isDocumentedDeprecated(m_reader.getMethodDocumentation(i)))); o << "virtual "; dumpType(o, returnType); if ( !paramCount ) { // prettier output for nullary methods o << " SAL_CALL " << methodName << "()"; } else { o << " SAL_CALL " << methodName << "( "; for (sal_uInt16 j=0; j < paramCount; j++) { paramName = rtl::OUStringToOString( m_reader.getMethodParameterName(i, j), RTL_TEXTENCODING_UTF8); paramType = rtl::OUStringToOString( m_reader.getMethodParameterTypeName(i, j), RTL_TEXTENCODING_UTF8); paramMode = m_reader.getMethodParameterFlags(i, j); switch (paramMode) { case RT_PARAM_IN: bConst = passByReference(paramType); bRef = bConst; break; case RT_PARAM_OUT: case RT_PARAM_INOUT: bConst = sal_False; bRef = sal_True; break; default: break; } dumpType(o, paramType, bConst, bRef); o << " " << paramName; if (j+1 < (sal_uInt16)paramCount) o << ", "; } o << " )"; } dumpExceptionSpecification(o, i, bWithRunTimeExcp); o << " = 0;\n"; } } void InterfaceType::dumpNormalGetCppuType(FileStream& o) { dumpGetCppuTypePreamble(o); o << indent() << "static typelib_TypeDescriptionReference * the_type = 0;\n"; o << indent() << "if ( !the_type )\n" << indent() << "{\n"; inc(); sal_Int16 nBases = m_reader.getSuperTypeCount(); OSL_ASSERT(nBases > 0); if (nBases == 1 && m_reader.getSuperTypeName(0) == "com/sun/star/uno/XInterface" ) { nBases = 0; } if (nBases > 0) { o << indent() << "typelib_TypeDescriptionReference * aSuperTypes[" << nBases << "];\n"; for (sal_Int16 i = 0; i < nBases; ++i) { o << indent() << "aSuperTypes[" << i << "] = ::cppu::UnoType< "; dumpType( o, rtl::OUStringToOString( m_reader.getSuperTypeName(i), RTL_TEXTENCODING_UTF8), true, false, false, true); o << " >::get().getTypeLibType();\n"; } } o << indent() << "typelib_static_mi_interface_type_init( &the_type, \"" << m_typeName.replace('/', '.') << "\", " << nBases << ", "; if ( nBases > 0 ) { o << "aSuperTypes );\n"; } else { o << "0 );\n"; } dec(); o << indent() << "}\n"; o << indent() << ("return * reinterpret_cast< ::com::sun::star::uno::Type * >(" " &the_type );\n"); dumpGetCppuTypePostamble(o); } void InterfaceType::dumpComprehensiveGetCppuType(FileStream& o) { if (!isPolymorphic()) codemaker::cppumaker::dumpNamespaceOpen(o, m_typeName, false); else o << "namespace cppu { "; o << " namespace detail {\n\n"; OString sType = m_typeName.copy(m_typeName.lastIndexOf('/') + 1); OString sStaticTypeClass = "the" + sType + "Type"; o << indent() << "struct " << sStaticTypeClass << " : public rtl::StaticWithInit< ::com::sun::star::uno::Type *, " << sStaticTypeClass << " >\n"; o << indent() << "{\n"; inc(); o << indent() << "::com::sun::star::uno::Type * operator()() const\n"; o << indent() << "{\n"; inc(); o << indent() << "::rtl::OUString sTypeName( \"" << m_typeName.replace('/', '.') << "\" );\n\n"; o << indent() << "// Start inline typedescription generation\n" << indent() << "typelib_InterfaceTypeDescription * pTD = 0;\n\n"; OSL_ASSERT(m_reader.getSuperTypeCount() > 0); o << indent() << "typelib_TypeDescriptionReference * aSuperTypes[" << m_reader.getSuperTypeCount() << "];\n"; for (sal_Int16 i = 0; i < m_reader.getSuperTypeCount(); ++i) { o << indent() << "aSuperTypes[" << i << "] = ::cppu::UnoType< "; dumpType( o, rtl::OUStringToOString( m_reader.getSuperTypeName(i), RTL_TEXTENCODING_UTF8), false, false, false, true); o << " >::get().getTypeLibType();\n"; } sal_uInt32 count = getMemberCount(); if (count) { o << indent() << "typelib_TypeDescriptionReference * pMembers[" << count << "] = { "; for (sal_uInt32 i = 0; i < count; i++) { o << "0"; if (i+1 < count) { o << ","; } else { o << " };\n"; } } sal_uInt32 index = 0; dumpCppuAttributeRefs(o, index); dumpCppuMethodRefs(o, index); } o << "\n" << indent() << "typelib_typedescription_newMIInterface(\n"; inc(); o << indent() << "&pTD,\n" << indent() << "sTypeName.pData, "; o << "0x00000000, 0x0000, 0x0000, 0x00000000, 0x00000000,\n"; // UIK o << indent() << m_reader.getSuperTypeCount() << ", aSuperTypes,\n"; if ( count ) { o << indent() << count << ",\n" << indent() << "pMembers );\n\n"; } else { o << indent() << count << ",\n" << indent() << "0 );\n\n"; } dec(); o << indent() << ("typelib_typedescription_register( (typelib_TypeDescription**)&pTD" " );\n"); if ( count ) { for (sal_uInt16 i=0; i < count; i++) { o << indent() << "typelib_typedescriptionreference_release( pMembers[" << i << "] );\n"; } } o << indent() << ("typelib_typedescription_release( (typelib_TypeDescription*)pTD" " );\n\n"); o << indent() << "return new ::com::sun::star::uno::Type( " << getTypeClass(m_typeName) << ", sTypeName ); // leaked\n"; dec(); o << indent() << "}\n"; dec(); o << indent() << "};\n\n"; if (!isPolymorphic()) codemaker::cppumaker::dumpNamespaceClose(o, m_typeName, false); else o << " }"; o << " }\n\n"; dumpGetCppuTypePreamble(o); o << indent() << "const ::com::sun::star::uno::Type &rRet = *detail::" << sStaticTypeClass << "::get();\n"; o << indent() << "// End inline typedescription generation\n"; o << indent() << "static bool bInitStarted = false;\n"; o << indent() << "if (!bInitStarted)\n"; o << indent() << "{\n"; inc(); o << indent() << "::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );\n"; o << indent() << "if (!bInitStarted)\n"; o << indent() << "{\n"; inc(); o << indent() << "OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();\n"; o << indent() << "bInitStarted = true;\n"; StringSet aTypes; // type for RuntimeException is always needed OString sRunTimeExceptionType("com/sun/star/uno/RuntimeException"); aTypes.insert(sRunTimeExceptionType); dumpCppuGetType(o, sRunTimeExceptionType, sal_True, CPPUTYPEDECL_ALLTYPES); dumpAttributesCppuDecl(o, &aTypes, CPPUTYPEDECL_ALLTYPES); dumpMethodsCppuDecl(o, &aTypes, CPPUTYPEDECL_ALLTYPES); if (count) { sal_uInt32 index = getInheritedMemberCount(); dumpCppuAttributes(o, index); dumpCppuMethods(o, index); } dec(); o << indent() << "}\n"; dec(); o << indent() << "}\n"; o << indent() << "else\n"; o << indent() << "{\n"; inc(); o << indent() << "OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();\n"; dec(); o << indent() << "}\n"; o << indent() << "return rRet;\n"; dumpGetCppuTypePostamble(o); } void InterfaceType::dumpCppuAttributeRefs(FileStream& o, sal_uInt32& index) { sal_uInt16 fieldCount = m_reader.getFieldCount(); RTFieldAccess access = RT_ACCESS_INVALID; OString fieldName; OString scope = m_typeName.replace('/', '.'); for (sal_uInt16 i=0; i < fieldCount; i++) { access = m_reader.getFieldFlags(i); if (access == RT_ACCESS_CONST || access == RT_ACCESS_INVALID) continue; fieldName = rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8); o << indent() << "::rtl::OUString sAttributeName" << i << "( \"" << scope.replace('/', '.') << "::" << fieldName << "\" );\n"; o << indent() << "typelib_typedescriptionreference_new( &pMembers[" << index << "],\n"; inc(38); o << indent() << "(typelib_TypeClass)::com::sun::star::uno::TypeClass_INTERFACE_ATTRIBUTE,\n" << indent() << "sAttributeName" << i << ".pData );\n"; dec(38); index++; } } void InterfaceType::dumpCppuMethodRefs(FileStream& o, sal_uInt32& index) { sal_uInt16 methodCount = m_reader.getMethodCount(); OString methodName; OString scope = m_typeName.replace('/', '.'); for (sal_uInt16 i = 0; i < methodCount; i++) { RTMethodMode flags = m_reader.getMethodFlags(i); if (flags == RT_MODE_ATTRIBUTE_GET || flags == RT_MODE_ATTRIBUTE_SET) { continue; } methodName = rtl::OUStringToOString( m_reader.getMethodName(i), RTL_TEXTENCODING_UTF8); o << indent() << "::rtl::OUString sMethodName" << i << "( \"" << scope.replace('/', '.') << "::" << methodName << "\" );\n"; o << indent() << "typelib_typedescriptionreference_new( &pMembers[" << index << "],\n"; inc(38); o << indent() << "(typelib_TypeClass)::com::sun::star::uno::TypeClass_INTERFACE_METHOD,\n" << indent() << "sMethodName" << i << ".pData );\n"; dec(38); index++; } } sal_uInt32 InterfaceType::getMemberCount() { sal_uInt16 count = 0; sal_uInt16 methodCount = m_reader.getMethodCount(); {for (sal_uInt16 i = 0; i < methodCount; ++i) { RTMethodMode flags = m_reader.getMethodFlags(i); if (flags != RT_MODE_ATTRIBUTE_GET && flags != RT_MODE_ATTRIBUTE_SET) { m_hasMethods = true; ++count; } }} sal_uInt16 fieldCount = m_reader.getFieldCount(); {for (sal_uInt16 i = 0; i < fieldCount; ++i) { RTFieldAccess flags = m_reader.getFieldFlags(i); if (flags != RT_ACCESS_CONST && flags != RT_ACCESS_INVALID) { m_hasAttributes = true; ++count; } }} return count; } namespace { class BaseOffset { public: BaseOffset(TypeManager const & theManager, typereg::Reader const & reader); sal_Int32 get() const { return offset; } private: void calculateBases(typereg::Reader const & reader); void calculate(typereg::Reader const & reader); TypeManager const & manager; std::set< rtl::OString > set; sal_Int32 offset; }; BaseOffset::BaseOffset( TypeManager const & theManager, typereg::Reader const & reader): manager(theManager) { offset = 0; calculateBases(reader); } void BaseOffset::calculateBases(typereg::Reader const & reader) { for (sal_Int16 i = 0; i < reader.getSuperTypeCount(); ++i) { typereg::Reader super( manager.getTypeReader( rtl::OUStringToOString( reader.getSuperTypeName(i), RTL_TEXTENCODING_UTF8))); if (super.isValid()) { calculate(super); } } } void BaseOffset::calculate(typereg::Reader const & reader) { if (set.insert( rtl::OUStringToOString(reader.getTypeName(), RTL_TEXTENCODING_UTF8)) .second) { calculateBases(reader); {for (sal_uInt16 i = 0; i < reader.getMethodCount(); ++i) { RTMethodMode flags = reader.getMethodFlags(i); if (flags != RT_MODE_ATTRIBUTE_GET && flags != RT_MODE_ATTRIBUTE_SET) { ++offset; } }} {for (sal_uInt16 i = 0; i < reader.getFieldCount(); ++i) { RTFieldAccess flags = reader.getFieldFlags(i); if (flags != RT_ACCESS_CONST && flags != RT_ACCESS_INVALID) { ++offset; } }} } } } void InterfaceType::addSpecialDependencies() { if (m_reader.getMethodCount() > 0 || m_reader.getFieldCount() > 0) { m_dependencies.add("com/sun/star/uno/RuntimeException"); } } void InterfaceType::addComprehensiveGetCppuTypeIncludes( codemaker::cppumaker::Includes & includes) const { // The comprehensive getCppuType method always includes a line // "getCppuType( (const ::com::sun::star::uno::RuntimeException*)0 );": includes.addCppuUnotypeHxx(); includes.add("com/sun/star/uno/RuntimeException"); } sal_uInt32 InterfaceType::checkInheritedMemberCount(const typereg::Reader*) { return BaseOffset(m_typeMgr, m_reader).get(); } sal_uInt32 InterfaceType::getInheritedMemberCount() { if (m_inheritedMemberCount == 0) { m_inheritedMemberCount = checkInheritedMemberCount(0); } return m_inheritedMemberCount; } void InterfaceType::dumpCppuAttributes(FileStream& o, sal_uInt32& index) { sal_uInt16 fieldCount = m_reader.getFieldCount(); RTFieldAccess access = RT_ACCESS_INVALID; OString fieldName; OString fieldType; OString scope = m_typeName.replace('/', '.'); sal_uInt32 absoluteIndex = index; if (m_hasAttributes) { o << "\n" << indent() << "typelib_InterfaceAttributeTypeDescription * pAttribute = 0;\n"; for (sal_uInt16 i=0; i < fieldCount; i++) { access = m_reader.getFieldFlags(i); if (access == RT_ACCESS_CONST || access == RT_ACCESS_INVALID) continue; rtl::OUString name(m_reader.getFieldName(i)); fieldName = rtl::OUStringToOString(name, RTL_TEXTENCODING_UTF8); fieldType = checkRealBaseType( rtl::OUStringToOString( m_reader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8), sal_True); o << indent() << "{\n"; inc(); o << indent() << "::rtl::OUString sAttributeType" << i << "( \"" << fieldType.replace('/', '.') << "\" );\n"; o << indent() << "::rtl::OUString sAttributeName" << i << "( \"" << scope.replace('/', '.') << "::" << fieldName << "\" );\n"; sal_Int32 getExceptions = dumpAttributeExceptionTypeNames( o, "get", name, RT_MODE_ATTRIBUTE_GET); sal_Int32 setExceptions = dumpAttributeExceptionTypeNames( o, "set", name, RT_MODE_ATTRIBUTE_SET); o << indent() << ("typelib_typedescription_newExtendedInterfaceAttribute(" " &pAttribute,\n"); inc(); o << indent() << absoluteIndex++ << ", sAttributeName" << i << ".pData,\n"; o << indent() << "(typelib_TypeClass)" << getTypeClass(fieldType) << ", sAttributeType" << i << ".pData,\n"; o << indent() << "sal_" << ((access & RT_ACCESS_READONLY) == 0 ? "False" : "True") << ", " << getExceptions << ", " << (getExceptions == 0 ? "0" : "the_getExceptions") << ", " << setExceptions << ", " << (setExceptions == 0 ? "0" : "the_setExceptions") << " );\n"; dec(); o << indent() << "typelib_typedescription_register( (typelib_TypeDescription**)&pAttribute );\n"; dec(); o << indent() << "}\n"; } o << indent() << "typelib_typedescription_release( (typelib_TypeDescription*)pAttribute );\n"; index = absoluteIndex; } } void InterfaceType::dumpCppuMethods(FileStream& o, sal_uInt32& index) { sal_uInt16 methodCount = m_reader.getMethodCount(); OString methodName, returnType, paramType, paramName; RTMethodMode methodMode = RT_MODE_INVALID; RTParamMode paramMode = RT_PARAM_INVALID; sal_Bool bWithRuntimeException = sal_True; sal_uInt32 absoluteIndex = index; if (m_hasMethods) { o << "\n" << indent() << "typelib_InterfaceMethodTypeDescription * pMethod = 0;\n"; OString scope = m_typeName.replace('/', '.'); sal_uInt16 paramCount = 0; for (sal_uInt16 i=0; i < methodCount; i++) { methodMode = m_reader.getMethodFlags(i); if (methodMode == RT_MODE_ATTRIBUTE_GET || methodMode == RT_MODE_ATTRIBUTE_SET) { continue; } methodName = rtl::OUStringToOString( m_reader.getMethodName(i), RTL_TEXTENCODING_UTF8); returnType = checkRealBaseType( rtl::OUStringToOString( m_reader.getMethodReturnTypeName(i), RTL_TEXTENCODING_UTF8), sal_True); paramCount = m_reader.getMethodParameterCount(i); if ( methodName.equals("acquire") || methodName.equals("release") ) { bWithRuntimeException = sal_False; } o << indent() << "{\n"; inc(); if (paramCount) { o << indent() << "typelib_Parameter_Init aParameters[" << paramCount << "];\n"; } for (sal_uInt16 j = 0; j < paramCount; j++) { paramName = rtl::OUStringToOString( m_reader.getMethodParameterName(i, j), RTL_TEXTENCODING_UTF8); paramType = checkRealBaseType( rtl::OUStringToOString( m_reader.getMethodParameterTypeName(i, j), RTL_TEXTENCODING_UTF8), sal_True); paramMode = m_reader.getMethodParameterFlags(i, j); o << indent() << "::rtl::OUString sParamName" << j << "( \"" << paramName << "\" );\n"; o << indent() << "::rtl::OUString sParamType" << j << "( \"" << paramType.replace('/', '.') << "\" );\n"; o << indent() << "aParameters[" << j << "].pParamName = sParamName" << j << ".pData;\n"; o << indent() << "aParameters[" << j << "].eTypeClass = (typelib_TypeClass)" << getTypeClass(paramType) << ";\n"; o << indent() << "aParameters[" << j << "].pTypeName = sParamType" << j << ".pData;\n"; if (paramMode == RT_PARAM_IN || paramMode == RT_PARAM_INOUT) o << indent() << "aParameters[" << j << "].bIn = sal_True;\n"; else o << indent() << "aParameters[" << j << "].bIn = sal_False;\n"; if (paramMode == RT_PARAM_OUT || paramMode == RT_PARAM_INOUT) o << indent() << "aParameters[" << j << "].bOut = sal_True;\n"; else o << indent() << "aParameters[" << j << "].bOut = sal_False;\n"; } sal_Int32 excCount = dumpExceptionTypeNames( o, "", i, bWithRuntimeException); o << indent() << "::rtl::OUString sReturnType" << i << "( \"" << returnType.replace('/', '.') << "\" );\n"; o << indent() << "::rtl::OUString sMethodName" << i << "( \"" << scope.replace('/', '.') << "::" << methodName << "\" );\n"; o << indent() << "typelib_typedescription_newInterfaceMethod( &pMethod,\n"; inc(); o << indent() << absoluteIndex++ << ", "; if (methodMode == RT_MODE_ONEWAY || methodMode == RT_MODE_ONEWAY_CONST) o << "sal_True,\n"; else o << "sal_False,\n"; o << indent() << "sMethodName" << i << ".pData,\n"; o << indent() << "(typelib_TypeClass)" << getTypeClass(returnType) << ", sReturnType" << i << ".pData,\n"; if (paramCount) o << indent() << paramCount << ", aParameters,\n"; else o << indent() << "0, 0,\n"; o << indent() << excCount << ", " << (excCount == 0 ? "0" : "the_Exceptions") << " );\n"; dec(); o << indent() << "typelib_typedescription_register( (typelib_TypeDescription**)&pMethod );\n"; dec(); o << indent() << "}\n"; } o << indent() << "typelib_typedescription_release( (typelib_TypeDescription*)pMethod );\n"; index = absoluteIndex; } } void InterfaceType::dumpAttributesCppuDecl(FileStream& o, StringSet* pFinishedTypes, CppuTypeDecl eDeclFlag) { sal_uInt16 fieldCount = m_reader.getFieldCount(); RTFieldAccess access = RT_ACCESS_INVALID; OString fieldName; OString fieldType; for (sal_uInt16 i=0; i < fieldCount; i++) { access = m_reader.getFieldFlags(i); if (access == RT_ACCESS_CONST || access == RT_ACCESS_INVALID) continue; fieldName = rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8); fieldType = rtl::OUStringToOString( m_reader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8); if (pFinishedTypes->count(fieldType) == 0) { pFinishedTypes->insert(fieldType); dumpCppuGetType(o, fieldType, sal_True, eDeclFlag); } } } void InterfaceType::dumpMethodsCppuDecl(FileStream& o, StringSet* pFinishedTypes, CppuTypeDecl eDeclFlag) { sal_uInt16 methodCount = m_reader.getMethodCount(); OString returnType, paramType, excType; sal_uInt16 paramCount = 0; sal_uInt16 excCount = 0; for (sal_uInt16 i=0; i < methodCount; i++) { returnType = rtl::OUStringToOString( m_reader.getMethodReturnTypeName(i), RTL_TEXTENCODING_UTF8); paramCount = m_reader.getMethodParameterCount(i); excCount = m_reader.getMethodExceptionCount(i); if (pFinishedTypes->count(returnType) == 0) { pFinishedTypes->insert(returnType); dumpCppuGetType(o, returnType, sal_True, eDeclFlag); } sal_uInt16 j; for (j=0; j < paramCount; j++) { paramType = rtl::OUStringToOString( m_reader.getMethodParameterTypeName(i, j), RTL_TEXTENCODING_UTF8); if (pFinishedTypes->count(paramType) == 0) { pFinishedTypes->insert(paramType); dumpCppuGetType(o, paramType, sal_True, eDeclFlag); } } for (j=0; j < excCount; j++) { excType = rtl::OUStringToOString( m_reader.getMethodExceptionTypeName(i, j), RTL_TEXTENCODING_UTF8); if (pFinishedTypes->count(excType) == 0) { pFinishedTypes->insert(excType); dumpCppuGetType(o, excType, sal_True, eDeclFlag); } } } } void InterfaceType::dumpExceptionSpecification( FileStream & out, sal_uInt32 methodIndex, bool runtimeException) { // exception specifications are undesirable in production code, but make // for useful assertions in debug builds (on platforms where they are // enforced at runtime) #ifndef DBG_UTIL (void) out; (void) methodIndex; (void) runtimeException; #else out << " throw ("; bool first = true; if (methodIndex <= SAL_MAX_UINT16) { sal_uInt16 count = m_reader.getMethodExceptionCount( static_cast< sal_uInt16 >(methodIndex)); for (sal_uInt16 i = 0; i < count; ++i) { rtl::OUString name( m_reader.getMethodExceptionTypeName( static_cast< sal_uInt16 >(methodIndex), i)); if ( name != "com/sun/star/uno/RuntimeException" ) { if (!first) { out << ", "; } first = false; out << scopedCppName( rtl::OUStringToOString(name, RTL_TEXTENCODING_UTF8)); } } } if (runtimeException) { if (!first) { out << ", "; } out << "::com::sun::star::uno::RuntimeException"; } out << ")"; #endif } void InterfaceType::dumpAttributeExceptionSpecification( FileStream & out, rtl::OUString const & name, RTMethodMode sort) { sal_uInt16 methodCount = m_reader.getMethodCount(); for (sal_uInt16 i = 0; i < methodCount; ++i) { if (m_reader.getMethodFlags(i) == sort && m_reader.getMethodName(i) == name) { dumpExceptionSpecification(out, i, true); return; } } dumpExceptionSpecification(out, 0xFFFFFFFF, true); } void InterfaceType::dumpExceptionTypeName( FileStream & out, char const * prefix, sal_uInt32 index, rtl::OUString name) { out << indent() << "::rtl::OUString the_" << prefix << "ExceptionName" << index << "( \"" << rtl::OUStringToOString(name, RTL_TEXTENCODING_UTF8).replace('/', '.') << "\" );\n"; } sal_Int32 InterfaceType::dumpExceptionTypeNames( FileStream & out, char const * prefix, sal_uInt16 methodIndex, bool runtimeException) { sal_Int32 count = 0; sal_uInt16 n = m_reader.getMethodExceptionCount(methodIndex); for (sal_uInt16 i = 0; i < n; ++i) { rtl::OUString name(m_reader.getMethodExceptionTypeName(methodIndex, i)); if ( name != "com/sun/star/uno/RuntimeException" ) { dumpExceptionTypeName(out, prefix, count++, name); } } if (runtimeException) { dumpExceptionTypeName( out, prefix, count++, rtl::OUString("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; } sal_Int32 InterfaceType::dumpAttributeExceptionTypeNames( FileStream & out, char const * prefix, rtl::OUString const & name, RTMethodMode sort) { sal_uInt16 methodCount = m_reader.getMethodCount(); for (sal_uInt16 i = 0; i < methodCount; ++i) { if (m_reader.getMethodFlags(i) == sort && m_reader.getMethodName(i) == name) { return dumpExceptionTypeNames(out, prefix, i, false); } } return 0; } //************************************************************************* // ConstantsType //************************************************************************* ConstantsType::ConstantsType(typereg::Reader& typeReader, const OString& typeName, const TypeManager& typeMgr) : CppuType(typeReader, typeName, typeMgr) { } ConstantsType::~ConstantsType() { } sal_Bool ConstantsType::dump(CppuOptions* pOptions) throw( CannotDumpException ) { if (!m_dependencies.isValid()) { return false; } addSpecialDependencies(); if (pOptions->isValid("-U")) m_cppuTypeDynamic = true; OString outPath; if (pOptions->isValid("-O")) outPath = pOptions->getOption("-O"); return dumpFiles(pOptions, outPath); } sal_Bool ConstantsType::dumpHFile( FileStream& o, codemaker::cppumaker::Includes & includes) throw( CannotDumpException ) { sal_Bool bSpecialDefine = sal_True; if (m_reader.getTypeClass() == RT_TYPE_CONSTANTS) { bSpecialDefine = sal_False; } OString headerDefine(dumpHeaderDefine(o, "HDL", bSpecialDefine)); o << "\n"; addDefaultHIncludes(includes); includes.dump(o, 0); o << "\n"; if (codemaker::cppumaker::dumpNamespaceOpen(o, m_typeName, true)) { o << "\n"; } o << "\n"; dumpDeclaration(o); o << "\n"; if (codemaker::cppumaker::dumpNamespaceClose(o, m_typeName, true)) { o << "\n"; } o << "\n#endif // "<< headerDefine << "\n"; return sal_True; } void ConstantsType::dumpDeclaration(FileStream& o) throw( CannotDumpException ) { sal_uInt16 fieldCount = m_reader.getFieldCount(); OString fieldName; OString fieldType; for (sal_uInt16 i=0; i < fieldCount; i++) { fieldName = rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8); fieldType = rtl::OUStringToOString( m_reader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8); o << "static const "; dumpType(o, fieldType); o << " " << fieldName << " = "; dumpConstantValue(o, i); o << ";\n"; } } sal_Bool ConstantsType::hasConstants() { return m_reader.getFieldCount() > 0; } sal_Bool ConstantsType::dumpHxxFile( FileStream& o, codemaker::cppumaker::Includes &) throw( CannotDumpException ) { sal_Bool bSpecialDefine = sal_True; if (m_reader.getTypeClass() == RT_TYPE_CONSTANTS) { bSpecialDefine = sal_False; } OString headerDefine(dumpHeaderDefine(o, "HPP", bSpecialDefine)); o << "\n"; rtl::OString suffix; if (bSpecialDefine) { suffix = m_name; } codemaker::cppumaker::Includes::dumpInclude(o, m_typeName, false, suffix); o << "\n#endif // "<< headerDefine << "\n"; return sal_True; } //************************************************************************* // ModuleType //************************************************************************* ModuleType::ModuleType(typereg::Reader& typeReader, const OString& typeName, const TypeManager& typeMgr) : ConstantsType(typeReader, typeName, typeMgr) { } ModuleType::~ModuleType() { } bool ModuleType::dumpFiles( CppuOptions * options, rtl::OString const & outPath) { rtl::OString tmpName(m_typeName); if (tmpName.equals("/")) { tmpName = "global"; } else { tmpName += "/" + m_typeName.copy(m_typeName.lastIndexOf('/') + 1); } return dumpFile(options, ".hdl", tmpName, outPath) && dumpFile(options, ".hpp", tmpName, outPath); } //************************************************************************* // StructureType //************************************************************************* namespace { void dumpTypeParameterName(FileStream & out, rtl::OString const & 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; }; out << "typeparam_" << name; } } StructureType::StructureType(typereg::Reader& typeReader, const OString& typeName, const TypeManager& typeMgr) : CppuType(typeReader, typeName, typeMgr) { } StructureType::~StructureType() { } sal_Bool StructureType::dumpHFile( FileStream& o, codemaker::cppumaker::Includes & includes) throw( CannotDumpException ) { dumpHFileContent(o, includes); return sal_True; } void StructureType::dumpDeclaration(FileStream& o) throw( CannotDumpException ) { o << "\n#ifdef SAL_W32\n" << "# pragma pack(push, 8)\n" << "#endif\n\n"; OSL_ASSERT(!isPolymorphic() || m_reader.getSuperTypeCount() == 0); //TODO o << indent(); dumpTemplateHead(o); o << "struct " << m_name; rtl::OString base; if (m_reader.getSuperTypeCount() != 0) { base = rtl::OUStringToOString( m_reader.getSuperTypeName(0), RTL_TEXTENCODING_UTF8); OSL_ASSERT(!base.isEmpty()); //TODO } if (!base.isEmpty()) { o << ": public " << scopedCppName(base); } o << " {\n"; inc(); o << indent() << "inline " << m_name << "() SAL_THROW(());\n"; sal_uInt16 members = m_reader.getFieldCount(); if (members > 0 || getInheritedMemberCount() > 0) { o << "\n" << indent() << "inline " << m_name << "("; bool prev = dumpSuperMember(o, base, true); for (sal_uInt16 i = 0; i < members; ++i) { if (prev) { o << ", "; } prev = true; rtl::OString type( rtl::OUStringToOString( m_reader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8)); if ((m_reader.getFieldFlags(i) & RT_ACCESS_PARAMETERIZED_TYPE) != 0) { dumpTypeParameterName(o, type); o << " const &"; } else { dumpType(o, type, true, true); } o << " " << rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8) << "_"; } o << ") SAL_THROW(());\n"; } if (members > 0) { o << "\n"; for (sal_uInt16 i = 0; i < members; ++i) { o << indent(); bool parameterized = ((m_reader.getFieldFlags(i) & RT_ACCESS_PARAMETERIZED_TYPE) != 0); rtl::OString type( rtl::OUStringToOString( m_reader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8)); if (parameterized) { dumpTypeParameterName(o, type); } else { dumpType(o, type); } o << " " << rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8); if (i == 0 && !base.isEmpty() && type != "double" && type != "hyper" && type != "unsigned hyper") { OSL_ASSERT(!parameterized); o << " CPPU_GCC3_ALIGN(" << scopedCppName(base) << ")"; } o << ";\n"; } } dec(); o << "};\n\n"; o << "#ifdef SAL_W32\n" << "# pragma pack(pop)\n" << "#endif\n\n"; } sal_Bool StructureType::dumpHxxFile( FileStream& o, codemaker::cppumaker::Includes & includes) throw( CannotDumpException ) { OString headerDefine(dumpHeaderDefine(o, "HPP")); o << "\n"; includes.dump(o, &m_typeName); o << "\n"; if (codemaker::cppumaker::dumpNamespaceOpen(o, m_typeName, false)) { o << "\n"; } o << "\n"; dumpTemplateHead(o); o << "inline " << m_name; dumpTemplateParameters(o); o << "::" << m_name << "() SAL_THROW(())\n"; inc(); OString superType; if (m_reader.getSuperTypeCount() >= 1) { superType = rtl::OUStringToOString( m_reader.getSuperTypeName(0), RTL_TEXTENCODING_UTF8); } sal_Bool first = sal_True; if (!superType.isEmpty()) { o << indent() << ": " << scopedCppName(superType) << "()\n"; first = sal_False; } sal_uInt16 fieldCount = m_reader.getFieldCount(); RTFieldAccess access = RT_ACCESS_INVALID; OString fieldName; OString fieldType; for (sal_uInt16 i=0; i < fieldCount; i++) { access = m_reader.getFieldFlags(i); if (access == RT_ACCESS_CONST || access == RT_ACCESS_INVALID) continue; fieldName = rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8); if (first) { first = sal_False; o << indent() << ": "; } else o << indent() << ", "; o << fieldName; dumpInitializer( o, (access & RT_ACCESS_PARAMETERIZED_TYPE) != 0, m_reader.getFieldTypeName(i)); o << "\n"; } dec(); o << "{\n}\n\n"; if (fieldCount > 0 || getInheritedMemberCount() > 0) { dumpTemplateHead(o); o << "inline " << m_name; dumpTemplateParameters(o); o << "::" << m_name << "("; sal_Bool superHasMember = dumpSuperMember(o, superType, sal_True); for (sal_uInt16 i=0; i < fieldCount; i++) { access = m_reader.getFieldFlags(i); if (access == RT_ACCESS_CONST || access == RT_ACCESS_INVALID) continue; fieldName = rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8); fieldType = rtl::OUStringToOString( m_reader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8); if (superHasMember) o << ", "; else superHasMember = sal_True; if ((access & RT_ACCESS_PARAMETERIZED_TYPE) != 0) { dumpTypeParameterName(o, fieldType); o << " const &"; } else { dumpType(o, fieldType, sal_True, sal_True); } o << " " << fieldName << "_"; } o << ") SAL_THROW(())\n"; inc(); first = sal_True; if (!superType.isEmpty()) { o << indent() << ": " << scopedCppName(superType) << "("; dumpSuperMember(o, superType, sal_False); o << ")\n"; first = sal_False; } for (sal_uInt16 i=0; i < fieldCount; i++) { access = m_reader.getFieldFlags(i); if (access == RT_ACCESS_CONST || access == RT_ACCESS_INVALID) continue; fieldName = rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8); if (first) { first = sal_False; o << indent() << ": "; } else o << indent() << ", "; o << fieldName << "(" << fieldName << "_)\n"; } dec(); o << "{\n}\n\n"; } if (isPolymorphic() && fieldCount > 0) { o << indent(); dumpTemplateHead(o); o << "\n"; o << indent(); o << "inline " << m_name; dumpTemplateParameters(o); o << "\n"; o << indent(); o << "make_" << m_name << "("; for (sal_uInt16 i = 0; i < fieldCount; ++i) { if (i > 0) { o << ", "; } rtl::OString type( rtl::OUStringToOString( m_reader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8)); if ((m_reader.getFieldFlags(i) & RT_ACCESS_PARAMETERIZED_TYPE) != 0) { dumpTypeParameterName(o, type); o << " const &"; } else { dumpType(o, type, true, true); } o << " " << rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8) << "_"; } o << ") SAL_THROW(())\n"; o << indent() << "{\n"; inc(); o << indent() << "return " << m_name; dumpTemplateParameters(o); o << "("; for (sal_uInt16 i = 0; i < fieldCount; ++i) { if (i > 0) { o << ", "; } o << rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8) << "_"; } o << ");\n"; dec(); o << indent() << "}\n\n"; } if (codemaker::cppumaker::dumpNamespaceClose(o, m_typeName, false)) { o << "\n"; } o << "\n"; dumpGetCppuType(o); o << "\n#endif // "<< headerDefine << "\n"; return sal_True; } void StructureType::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(); if (isPolymorphic()) { out << indent() << "::rtl::OStringBuffer the_buffer(\"" << m_typeName.replace('/', '.') << "<\");\n"; sal_uInt16 n = m_reader.getReferenceCount(); for (sal_uInt16 i = 0; i < n; ++i) { out << indent() << ("the_buffer.append(::rtl::OUStringToOString(" "::cppu::getTypeFavourChar(static_cast< "); dumpTypeParameterName( out, rtl::OUStringToOString( m_reader.getReferenceTypeName(i), RTL_TEXTENCODING_UTF8)); out << " * >(0)).getTypeName(), RTL_TEXTENCODING_UTF8));\n"; if (i != n - 1) { out << indent() << "the_buffer.append(',');\n"; } } out << indent() << "the_buffer.append('>');\n"; } out << indent() << "::typelib_static_type_init(&the_type, " << getTypeClass(m_typeName, true) << ", "; if (isPolymorphic()) { out << "the_buffer.getStr()"; } else { out << "\"" << m_typeName.replace('/', '.') << "\""; } out << ");\n"; dec(); out << indent() << "}\n" << indent() << ("return *reinterpret_cast< ::com::sun::star::uno::Type * >(" "&the_type);\n"); dumpGetCppuTypePostamble(out); } void StructureType::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(); if (isPolymorphic()) { out << indent() << "::rtl::OStringBuffer the_buffer(\"" << m_typeName.replace('/', '.') << "<\");\n"; sal_uInt16 n = m_reader.getReferenceCount(); for (sal_uInt16 i = 0; i < n; ++i) { out << indent() << ("the_buffer.append(::rtl::OUStringToOString(" "::cppu::getTypeFavourChar(static_cast< "); dumpTypeParameterName( out, rtl::OUStringToOString( m_reader.getReferenceTypeName(i), RTL_TEXTENCODING_UTF8)); out << " * >(0)).getTypeName(), RTL_TEXTENCODING_UTF8));\n"; if (i != n - 1) { out << indent() << "the_buffer.append(',');\n"; } } out << indent() << "the_buffer.append('>');\n"; } out << indent() << "::typelib_TypeDescriptionReference * the_members[] = {\n"; inc(); sal_uInt16 fields = m_reader.getFieldCount(); for (sal_uInt16 i = 0; i < fields; ++i) { out << indent(); rtl::OString type( rtl::OUStringToOString( m_reader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8)); if ((m_reader.getFieldFlags(i) & RT_ACCESS_PARAMETERIZED_TYPE) != 0) { out << "::cppu::getTypeFavourChar(static_cast< "; dumpTypeParameterName(out, type); out << " * >(0))"; } else { out << "::cppu::UnoType< "; dumpType(out, type, false, false, false, true); out << " >::get()"; } out << ".getTypeLibType()" << (i == fields - 1 ? " };" : ",") << "\n"; } dec(); if (isPolymorphic()) { out << indent() << "static ::sal_Bool const the_parameterizedTypes[] = { "; for (sal_uInt16 i = 0; i < fields; ++i) { if (i != 0) { out << ", "; } out << (((m_reader.getFieldFlags(i) & RT_ACCESS_PARAMETERIZED_TYPE) == 0) ? "false" : "true"); } out << " };\n"; } out << indent() << "::typelib_static_struct_type_init(&the_type, "; if (isPolymorphic()) { out << "the_buffer.getStr()"; } else { out << "\"" << m_typeName.replace('/', '.') << "\""; } out << ", "; if (m_reader.getSuperTypeCount() == 0) { out << "0"; } else { out << "::cppu::UnoType< "; dumpType( out, rtl::OUStringToOString( m_reader.getSuperTypeName(0), RTL_TEXTENCODING_UTF8), false, false, false, true); out << " >::get().getTypeLibType()"; } out << ", " << fields << ", the_members, " << (isPolymorphic() ? "the_parameterizedTypes" : "0") << ");\n"; dec(); out << indent() << "}\n" << indent() << ("return *reinterpret_cast< ::com::sun::star::uno::Type * >(" "&the_type);\n"); dumpGetCppuTypePostamble(out); } void StructureType::dumpComprehensiveGetCppuType(FileStream & out) { if (!isPolymorphic()) codemaker::cppumaker::dumpNamespaceOpen(out, m_typeName, false); else out << "namespace cppu { "; out << " namespace detail {\n\n"; OString sType = m_typeName.copy(m_typeName.lastIndexOf('/') + 1); OString sStaticTypeClass = "the" + sType + "Type"; out << indent(); if (isPolymorphic()) dumpTemplateHead(out); out << "struct " << sStaticTypeClass << " : public rtl::StaticWithInit< ::com::sun::star::uno::Type *, "; out << sStaticTypeClass; if (isPolymorphic()) dumpTemplateParameters(out); out << " >\n"; out << indent() << "{\n"; inc(); out << indent() << "::com::sun::star::uno::Type * operator()() const\n"; out << indent() << "{\n"; inc(); if (isPolymorphic()) { out << indent() << "::rtl::OUStringBuffer the_buffer;\n" << indent() << "the_buffer.appendAscii(RTL_CONSTASCII_STRINGPARAM(\"" << m_typeName.replace('/', '.') << "<\"));\n"; sal_uInt16 n = m_reader.getReferenceCount(); for (sal_uInt16 i = 0; i < n; ++i) { out << indent() << "the_buffer.append(::cppu::getTypeFavourChar(static_cast< "; dumpTypeParameterName( out, rtl::OUStringToOString( m_reader.getReferenceTypeName(i), RTL_TEXTENCODING_UTF8)); out << " * >(0)).getTypeName());\n"; if (i != n - 1) { out << indent() << ("the_buffer.append(" "static_cast< ::sal_Unicode >(','));\n"); } } out << indent() << "the_buffer.append(static_cast< ::sal_Unicode >('>'));\n" << indent() << "::rtl::OUString the_name(the_buffer.makeStringAndClear());\n"; } else { out << indent() << "::rtl::OUString the_name( \"" << m_typeName.replace('/', '.') << "\" );\n"; } sal_uInt16 fields = m_reader.getFieldCount(); typedef std::map< rtl::OString, sal_uInt32 > Map; Map parameters; Map types; {for (sal_uInt16 i = 0; i < fields; ++i) { rtl::OString type( rtl::OUStringToOString( m_reader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8)); if ((m_reader.getFieldFlags(i) & RT_ACCESS_PARAMETERIZED_TYPE) != 0) { if (parameters.insert( Map::value_type( type, static_cast< sal_uInt32 >(parameters.size()))). second) { sal_uInt32 n = static_cast< sal_uInt32 >(parameters.size() - 1); out << indent() << "::com::sun::star::uno::Type const & the_ptype" << n << " = ::cppu::getTypeFavourChar(static_cast< "; dumpTypeParameterName(out, type); out << " * >(0));\n" << indent() << "::typelib_TypeClass the_pclass" << n << " = (::typelib_TypeClass) the_ptype" << n << ".getTypeClass();\n" << indent() << "::rtl::OUString the_pname" << n << "(the_ptype" << n << ".getTypeName());\n"; } } else if (types.insert( Map::value_type( type, static_cast< sal_uInt32 >(types.size()))). second) { if ((codemaker::UnoType::getSort(type) == codemaker::UnoType::SORT_COMPLEX) && codemaker::UnoType::decompose(type) != m_typeName) // take care of recursion like struct S { sequence x; }; { out << indent() << "::cppu::UnoType< "; dumpType(out, type, false, false, false, true); out << " >::get();\n"; } // 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) << "( \"" << checkRealBaseType(type, true).replace('/', '.') << "\" );\n"; } out << indent() << "::rtl::OUString the_name" << i << "( \"" << rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8).replace( '/', '.') << "\" );\n"; }} out << indent() << "::typelib_StructMember_Init the_members[] = {\n"; inc(); {for (sal_uInt16 i = 0; i < fields; ++i) { out << indent() << "{ { "; rtl::OString type( rtl::OUStringToOString( m_reader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8)); if ((m_reader.getFieldFlags(i) & RT_ACCESS_PARAMETERIZED_TYPE) != 0) { sal_uInt32 n = parameters.find(type)->second; out << "the_pclass" << n << ", the_pname" << n << ".pData"; } else { out << getTypeClass(type, true) << ", the_tname" << types.find(type)->second << ".pData"; } out << ", the_name" << i << ".pData }, " << ((m_reader.getFieldFlags(i) & RT_ACCESS_PARAMETERIZED_TYPE) == 0 ? "false" : "true") << " }" << (i == fields - 1 ? " };" : ",") << "\n"; }} dec(); out << indent() << "::typelib_TypeDescription * the_newType = 0;\n"; out << indent() << "::typelib_typedescription_newStruct(&the_newType, the_name.pData, "; if (m_reader.getSuperTypeCount() == 0) { out << "0"; } else { out << "::cppu::UnoType< "; dumpType( out, rtl::OUStringToOString( m_reader.getSuperTypeName(0), RTL_TEXTENCODING_UTF8), false, false, false, true); out << " >::get().getTypeLibType()"; } out << ", " << fields << ", the_members);\n"; out << indent() << "::typelib_typedescription_register(&the_newType);\n"; out << indent() << "::typelib_typedescription_release(the_newType);\n"; out << indent() << "return new ::com::sun::star::uno::Type(" << getTypeClass(m_typeName) << ", the_name); // leaked\n"; dec(); out << indent() << "}\n"; dec(); out << indent() << "};\n"; if (!isPolymorphic()) codemaker::cppumaker::dumpNamespaceClose(out, m_typeName, false); else out << " }"; out << " }\n\n"; dumpGetCppuTypePreamble(out); out << indent() << "return *detail::" << sStaticTypeClass; if (isPolymorphic()) dumpTemplateParameters(out); out << "::get();\n"; dumpGetCppuTypePostamble(out); } sal_Bool StructureType::dumpSuperMember(FileStream& o, const OString& superType, sal_Bool bWithType) { sal_Bool hasMember = sal_False; if (!superType.isEmpty()) { typereg::Reader aSuperReader(m_typeMgr.getTypeReader(superType)); if (aSuperReader.isValid()) { rtl::OString superSuper; if (aSuperReader.getSuperTypeCount() >= 1) { superSuper = rtl::OUStringToOString( aSuperReader.getSuperTypeName(0), RTL_TEXTENCODING_UTF8); } hasMember = dumpSuperMember(o, superSuper, bWithType); sal_uInt16 fieldCount = aSuperReader.getFieldCount(); RTFieldAccess access = RT_ACCESS_INVALID; OString fieldName; OString fieldType; for (sal_uInt16 i=0; i < fieldCount; i++) { access = aSuperReader.getFieldFlags(i); if (access == RT_ACCESS_CONST || access == RT_ACCESS_INVALID) continue; fieldName = rtl::OUStringToOString( aSuperReader.getFieldName(i), RTL_TEXTENCODING_UTF8); fieldType = rtl::OUStringToOString( aSuperReader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8); if (hasMember) { o << ", "; } else { hasMember = (fieldCount > 0); } if (bWithType) { dumpType(o, fieldType, sal_True, sal_True); o << " "; } o << fieldName << "_"; } } } return hasMember; } void StructureType::addLightGetCppuTypeIncludes( codemaker::cppumaker::Includes & includes) const { includes.addType(); includes.addCppuUnotypeHxx(); includes.addSalTypesH(); includes.addTypelibTypeclassH(); includes.addTypelibTypedescriptionH(); if (isPolymorphic()) { includes.addRtlStrbufHxx(); includes.addRtlTextencH(); includes.addRtlUstringHxx(); } } void StructureType::addNormalGetCppuTypeIncludes( codemaker::cppumaker::Includes & includes) const { includes.addType(); includes.addCppuUnotypeHxx(); includes.addSalTypesH(); includes.addTypelibTypeclassH(); includes.addTypelibTypedescriptionH(); if (isPolymorphic()) { includes.addRtlStrbufHxx(); includes.addRtlTextencH(); includes.addRtlUstringHxx(); } } void StructureType::addComprehensiveGetCppuTypeIncludes( codemaker::cppumaker::Includes & includes) const { includes.addType(); includes.addCppuUnotypeHxx(); includes.addRtlInstanceHxx(); includes.addOslMutexHxx(); includes.addRtlUstringH(); includes.addRtlUstringHxx(); includes.addSalTypesH(); includes.addTypelibTypeclassH(); includes.addTypelibTypedescriptionH(); if (isPolymorphic()) { includes.addRtlStringH(); includes.addRtlUstrbufHxx(); } } bool StructureType::isPolymorphic() const { return m_reader.getReferenceCount() > 0; } void StructureType::dumpTemplateHead(FileStream & out) const { if (isPolymorphic()) { out << "template< "; for (sal_uInt16 i = 0; i < m_reader.getReferenceCount(); ++i) { if (i != 0) { out << ", "; } OSL_ASSERT( m_reader.getReferenceFlags(i) == RT_ACCESS_INVALID && m_reader.getReferenceSort(i) == RT_REF_TYPE_PARAMETER); out << "typename "; dumpTypeParameterName( out, rtl::OUStringToOString( m_reader.getReferenceTypeName(i), RTL_TEXTENCODING_UTF8)); } out << " > "; } } void StructureType::dumpTemplateParameters(FileStream & out) const { if (isPolymorphic()) { out << "< "; for (sal_uInt16 i = 0; i < m_reader.getReferenceCount(); ++i) { if (i != 0) { out << ", "; } OSL_ASSERT( m_reader.getReferenceFlags(i) == RT_ACCESS_INVALID && m_reader.getReferenceSort(i) == RT_REF_TYPE_PARAMETER); dumpTypeParameterName( out, rtl::OUStringToOString( m_reader.getReferenceTypeName(i), RTL_TEXTENCODING_UTF8)); } out << " >"; } } //************************************************************************* // ExceptionType //************************************************************************* ExceptionType::ExceptionType(typereg::Reader& typeReader, const OString& typeName, const TypeManager& typeMgr) : CppuType(typeReader, typeName, typeMgr) { } ExceptionType::~ExceptionType() { } sal_Bool ExceptionType::dumpHFile( FileStream& o, codemaker::cppumaker::Includes & includes) throw( CannotDumpException ) { dumpHFileContent(o, includes); return sal_True; } void ExceptionType::dumpDeclaration(FileStream& o) throw( CannotDumpException ) { o << "\nclass CPPU_GCC_DLLPUBLIC_EXPORT " << m_name; OString superType; if (m_reader.getSuperTypeCount() >= 1) { superType = rtl::OUStringToOString( m_reader.getSuperTypeName(0), RTL_TEXTENCODING_UTF8); } if (!superType.isEmpty()) o << " : public " << scopedCppName(superType); o << "\n{\npublic:\n"; inc(); o << indent() << "inline CPPU_GCC_DLLPRIVATE " << m_name << "() SAL_THROW(());\n\n"; sal_uInt16 fieldCount = m_reader.getFieldCount(); RTFieldAccess access = RT_ACCESS_INVALID; OString fieldName; OString fieldType; sal_uInt16 i = 0; if (fieldCount > 0 || getInheritedMemberCount() > 0) { o << indent() << "inline CPPU_GCC_DLLPRIVATE " << m_name << "("; sal_Bool superHasMember = dumpSuperMember(o, superType, sal_True); for (i=0; i < fieldCount; i++) { access = m_reader.getFieldFlags(i); if (access == RT_ACCESS_CONST || access == RT_ACCESS_INVALID) continue; fieldName = rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8); fieldType = rtl::OUStringToOString( m_reader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8); if (superHasMember) o << ", "; else superHasMember = sal_True; dumpType(o, fieldType, sal_True, sal_True); o << " " << fieldName << "_"; } o << ") SAL_THROW(());\n\n"; } o << indent() << "inline CPPU_GCC_DLLPRIVATE " << m_name << "(" << m_name << " const &);\n\n" << indent() << "inline CPPU_GCC_DLLPRIVATE ~" << m_name << "();\n\n" << indent() << "inline CPPU_GCC_DLLPRIVATE " << m_name << " & operator =(" << m_name << " const &);\n\n"; for (i=0; i < fieldCount; i++) { access = m_reader.getFieldFlags(i); if (access == RT_ACCESS_CONST || access == RT_ACCESS_INVALID) continue; fieldName = rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8); fieldType = rtl::OUStringToOString( m_reader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8); o << indent(); dumpType(o, fieldType); o << " " << fieldName; if (i == 0 && !superType.isEmpty() && !fieldType.equals("double") && !fieldType.equals("hyper") && !fieldType.equals("unsigned hyper")) { o << " CPPU_GCC3_ALIGN( " << scopedCppName(superType) << " )"; } o << ";\n"; } dec(); o << "};\n\n"; } sal_Bool ExceptionType::dumpHxxFile( FileStream& o, codemaker::cppumaker::Includes & includes) throw( CannotDumpException ) { OString headerDefine(dumpHeaderDefine(o, "HPP")); o << "\n"; addDefaultHxxIncludes(includes); includes.dump(o, &m_typeName); o << "\n"; if (codemaker::cppumaker::dumpNamespaceOpen(o, m_typeName, false)) { o << "\n"; } o << "\n"; o << "inline " << m_name << "::" << m_name << "() SAL_THROW(())\n"; inc(); OString superType; if (m_reader.getSuperTypeCount() >= 1) { superType = rtl::OUStringToOString( m_reader.getSuperTypeName(0), RTL_TEXTENCODING_UTF8); } sal_Bool first = sal_True; if (!superType.isEmpty()) { o << indent() << ": " << scopedCppName(superType) << "()\n"; first = sal_False; } sal_uInt16 fieldCount = m_reader.getFieldCount(); RTFieldAccess access = RT_ACCESS_INVALID; OString fieldName; OString fieldType; for (sal_uInt16 i=0; i < fieldCount; i++) { access = m_reader.getFieldFlags(i); if (access == RT_ACCESS_CONST || access == RT_ACCESS_INVALID) continue; fieldName = rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8); if (first) { first = sal_False; o << indent() << ": "; } else o << indent() << ", "; o << fieldName; dumpInitializer(o, false, m_reader.getFieldTypeName(i)); o << "\n"; } dec(); if ( !m_cppuTypeDynamic ) { o << "{\n"; inc(); dumpCppuGetType(o, m_typeName, sal_True); dec(); o << "}\n\n"; } else { o << "{ }\n\n"; } if (fieldCount > 0 || getInheritedMemberCount() > 0) { o << indent() << "inline " << m_name << "::" << m_name << "("; sal_Bool superHasMember = dumpSuperMember(o, superType, sal_True); for (sal_uInt16 i=0; i < fieldCount; i++) { access = m_reader.getFieldFlags(i); if (access == RT_ACCESS_CONST || access == RT_ACCESS_INVALID) continue; fieldName = rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8); fieldType = rtl::OUStringToOString( m_reader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8); if (superHasMember) o << ", "; else superHasMember = sal_True; dumpType(o, fieldType, sal_True, sal_True); o << " " << fieldName << "_"; } o << ") SAL_THROW(())\n"; inc(); first = sal_True; if (!superType.isEmpty()) { o << indent() << ": " << scopedCppName(superType) << "("; dumpSuperMember(o, superType, sal_False); o << ")\n"; first = sal_False; } for (sal_uInt16 i=0; i < fieldCount; i++) { access = m_reader.getFieldFlags(i); if (access == RT_ACCESS_CONST || access == RT_ACCESS_INVALID) continue; fieldName = rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8); if (first) { first = sal_False; o << indent() << ": "; } else o << indent() << ", "; o << fieldName << "(" << fieldName << "_)\n"; } dec(); if ( !m_cppuTypeDynamic ) { o << "{\n"; inc(); dumpCppuGetType(o, m_typeName, sal_True); dec(); o << "}\n\n"; } else { o << "{ }\n\n"; } } o << indent() << m_name << "::" << m_name << "(" << m_name << " const & the_other)"; first = true; if (!superType.isEmpty()) { o << ": " << scopedCppName(superType) << "(the_other)"; first = false; } for (sal_uInt16 i = 0; i < fieldCount; ++i) { rtl::OString name( rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8)); o << (first ? ": " : ", ") << name << "(the_other." << name << ")"; first = false; } o << indent() << " {}\n\n" << indent() << m_name << "::~" << m_name << "() {}\n\n" << indent() << m_name << " & " << m_name << "::operator =(" << m_name << " const & the_other) {\n"; inc(); o << indent() << ("//TODO: Just like its implicitly-defined counterpart, this function" " definition is not exception-safe\n"); if (!superType.isEmpty()) { o << indent() << scopedCppName(superType) << "::operator =(the_other);\n"; } for (sal_uInt16 i = 0; i < fieldCount; ++i) { rtl::OString name( rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8)); o << indent() << name << " = the_other." << name << ";\n"; } o << indent() << "return *this;\n"; dec(); o << indent() << "}\n\n"; if (codemaker::cppumaker::dumpNamespaceClose(o, m_typeName, false)) { o << "\n"; } o << "\n"; dumpGetCppuType(o); o << "\n#endif // "<< headerDefine << "\n"; return sal_True; } sal_Bool ExceptionType::dumpSuperMember(FileStream& o, const OString& superType, sal_Bool bWithType) { sal_Bool hasMember = sal_False; if (!superType.isEmpty()) { typereg::Reader aSuperReader(m_typeMgr.getTypeReader(superType)); if (aSuperReader.isValid()) { rtl::OString superSuper; if (aSuperReader.getSuperTypeCount() >= 1) { superSuper = rtl::OUStringToOString( aSuperReader.getSuperTypeName(0), RTL_TEXTENCODING_UTF8); } hasMember = dumpSuperMember(o, superSuper, bWithType); sal_uInt16 fieldCount = aSuperReader.getFieldCount(); RTFieldAccess access = RT_ACCESS_INVALID; OString fieldName; OString fieldType; for (sal_uInt16 i=0; i < fieldCount; i++) { access = aSuperReader.getFieldFlags(i); if (access == RT_ACCESS_CONST || access == RT_ACCESS_INVALID) continue; fieldName = rtl::OUStringToOString( aSuperReader.getFieldName(i), RTL_TEXTENCODING_UTF8); fieldType = rtl::OUStringToOString( aSuperReader.getFieldTypeName(i), RTL_TEXTENCODING_UTF8); if (hasMember) { o << ", "; } else { hasMember = (fieldCount > 0); } if (bWithType) { dumpType(o, fieldType, sal_True, sal_True); o << " "; } o << fieldName << "_"; } } } return hasMember; } //************************************************************************* // EnumType //************************************************************************* EnumType::EnumType(typereg::Reader& typeReader, const OString& typeName, const TypeManager& typeMgr) : CppuType(typeReader, typeName, typeMgr) { } EnumType::~EnumType() { } sal_Bool EnumType::dumpHFile( FileStream& o, codemaker::cppumaker::Includes & includes) throw( CannotDumpException ) { dumpHFileContent(o, includes); return sal_True; } void EnumType::dumpDeclaration(FileStream& o) throw( CannotDumpException ) { o << "\nenum " << m_name << "\n{\n"; inc(); sal_uInt16 fieldCount = m_reader.getFieldCount(); RTFieldAccess access = RT_ACCESS_INVALID; RTConstValue constValue; OString fieldName; sal_Int32 value=0; for (sal_uInt16 i=0; i < fieldCount; i++) { access = m_reader.getFieldFlags(i); if (access != RT_ACCESS_CONST) continue; fieldName = rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8); constValue = m_reader.getFieldValue(i); if (constValue.m_type == RT_TYPE_INT32) value = constValue.m_value.aLong; else value++; o << indent() << m_name << "_" << fieldName << " = " << value << ",\n"; } o << indent() << m_name << "_MAKE_FIXED_SIZE = SAL_MAX_ENUM\n"; dec(); o << "};\n\n"; } sal_Bool EnumType::dumpHxxFile( FileStream& o, codemaker::cppumaker::Includes & includes) throw( CannotDumpException ) { OString headerDefine(dumpHeaderDefine(o, "HPP")); o << "\n"; addDefaultHxxIncludes(includes); includes.dump(o, &m_typeName); o << "\n"; dumpGetCppuType(o); o << "\n#endif // "<< headerDefine << "\n"; return sal_True; } 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() << "\"" << m_typeName.replace('/', '.') << "\",\n" << indent() << scopedCppName(m_typeName) << "_" << rtl::OUStringToOString(m_reader.getFieldName(0), RTL_TEXTENCODING_UTF8) << " );\n"; dec(31); dec(); o << indent() << "}\n"; o << indent() << ("return * reinterpret_cast< ::com::sun::star::uno::Type * >(" " &the_type );\n"); dumpGetCppuTypePostamble(o); } void EnumType::dumpComprehensiveGetCppuType(FileStream& o) { if (!isPolymorphic()) codemaker::cppumaker::dumpNamespaceOpen(o, m_typeName, false); else o << "namespace cppu { "; o << " namespace detail {\n\n"; OString sType = m_typeName.copy(m_typeName.lastIndexOf('/') + 1); OString sStaticTypeClass = "the" + sType + "Type"; o << indent() << "struct " << sStaticTypeClass << " : public rtl::StaticWithInit< ::com::sun::star::uno::Type *, " << sStaticTypeClass << " >\n"; o << indent() << "{\n"; inc(); o << indent() << "::com::sun::star::uno::Type * operator()() const\n"; o << indent() << "{\n"; inc(); o << indent() << "::rtl::OUString sTypeName( \"" << m_typeName.replace('/', '.') << "\" );\n\n"; o << indent() << "// Start inline typedescription generation\n" << indent() << "typelib_TypeDescription * pTD = 0;\n\n"; sal_uInt16 count = m_reader.getFieldCount(); o << indent() << "rtl_uString* enumValueNames[" << count << "];\n"; sal_uInt16 i; for (i = 0; i < count; i++) { o << indent() << "::rtl::OUString sEnumValue" << i << "( \"" << rtl::OUStringToOString( m_reader.getFieldName(i), RTL_TEXTENCODING_UTF8) << "\" );\n"; o << indent() << "enumValueNames[" << i << "] = sEnumValue" << i << ".pData;\n"; } o << "\n" << indent() << "sal_Int32 enumValues[" << count << "];\n"; RTConstValue constValue; sal_Int32 value=0; for (i = 0; i < count; i++) { o << indent() << "enumValues[" << i << "] = "; constValue = m_reader.getFieldValue(i); if (constValue.m_type == RT_TYPE_INT32) value = constValue.m_value.aLong; else value++; o << value << ";\n"; } o << "\n" << indent() << "typelib_typedescription_newEnum( &pTD,\n"; inc(); o << indent() << "sTypeName.pData,\n" << indent() << "(sal_Int32)" << scopedCppName(m_typeName, sal_False) << "_" << rtl::OUStringToOString(m_reader.getFieldName(0), RTL_TEXTENCODING_UTF8) << ",\n" << indent() << count << ", 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 ::com::sun::star::uno::Type( " << getTypeClass(m_typeName) << ", sTypeName ); // leaked\n"; dec(); o << indent() << "}\n"; dec(); o << indent() << "};\n\n"; if (!isPolymorphic()) codemaker::cppumaker::dumpNamespaceClose(o, m_typeName, false); else o << " }"; o << " }\n\n"; dumpGetCppuTypePreamble(o); o << indent() << "return *detail::" << sStaticTypeClass << "::get();\n"; dumpGetCppuTypePostamble(o); } //************************************************************************* // TypeDefType //************************************************************************* TypeDefType::TypeDefType(typereg::Reader& typeReader, const OString& typeName, const TypeManager& typeMgr) : CppuType(typeReader, typeName, typeMgr) { } TypeDefType::~TypeDefType() { } sal_Bool TypeDefType::dumpHFile( FileStream& o, codemaker::cppumaker::Includes & includes) throw( CannotDumpException ) { OString headerDefine(dumpHeaderDefine(o, "HDL")); o << "\n"; addDefaultHIncludes(includes); includes.dump(o, 0); o << "\n"; if (codemaker::cppumaker::dumpNamespaceOpen(o, m_typeName, false)) { o << "\n"; } dumpDeclaration(o); if (codemaker::cppumaker::dumpNamespaceClose(o, m_typeName, false)) { o << "\n"; } o << "#endif // "<< headerDefine << "\n"; return sal_True; } void TypeDefType::dumpDeclaration(FileStream& o) throw( CannotDumpException ) { o << "\ntypedef "; dumpType( o, rtl::OUStringToOString( m_reader.getSuperTypeName(0), RTL_TEXTENCODING_UTF8)); o << " " << m_name << ";\n\n"; } sal_Bool TypeDefType::dumpHxxFile( FileStream& o, codemaker::cppumaker::Includes & includes) throw( CannotDumpException ) { OString headerDefine(dumpHeaderDefine(o, "HPP")); o << "\n"; addDefaultHxxIncludes(includes); includes.dump(o, &m_typeName); o << "\n"; o << "\n#endif // "<< headerDefine << "\n"; return sal_True; } //************************************************************************* // ConstructiveType //************************************************************************* sal_Bool ConstructiveType::dumpHFile( FileStream &, codemaker::cppumaker::Includes &) throw (CannotDumpException) { OSL_ASSERT(false); return false; } bool ConstructiveType::dumpFiles( CppuOptions * options, rtl::OString const & outPath) { return dumpFile(options, ".hpp", m_typeName, outPath); } //************************************************************************* // ServiceType //************************************************************************* namespace { void includeExceptions( codemaker::cppumaker::Includes & includes, codemaker::ExceptionTreeNode const * node) { if (node->present) { includes.add(node->name); } else { for (codemaker::ExceptionTreeNode::Children::const_iterator i( node->children.begin()); i != node->children.end(); ++i) { includeExceptions(includes, *i); } } } } bool ServiceType::isSingleInterfaceBased() { return m_reader.getSuperTypeCount() == 1; } sal_Bool ServiceType::dumpHxxFile( FileStream & o, codemaker::cppumaker::Includes & includes) throw (CannotDumpException) { sal_uInt16 ctors = m_reader.getMethodCount(); if (ctors > 0) { //TODO: Decide whether the types added to includes should rather be // added to m_dependencies (and thus be generated during // dumpDependedTypes): includes.addCassert(); includes.addReference(); includes.addRtlUstringH(); includes.addRtlUstringHxx(); includes.add("com/sun/star/uno/DeploymentException"); includes.add("com/sun/star/uno/XComponentContext"); for (sal_uInt16 i = 0; i < ctors; ++i) { if (isDefaultConstructor(i)) { includes.add("com/sun/star/uno/Exception"); includes.add("com/sun/star/uno/RuntimeException"); } else { if (!hasRestParameter(i)) { includes.addAny(); includes.addSequence(); sal_uInt16 params = m_reader.getMethodParameterCount(i); for (sal_uInt16 j = 0; j < params; ++j) { if (codemaker::UnoType::getSort( codemaker::UnoType::decompose( rtl::OUStringToOString( m_reader.getMethodParameterTypeName( i, j), RTL_TEXTENCODING_UTF8), 0, 0)) == codemaker::UnoType::SORT_CHAR) { includes.addCppuUnotypeHxx(); break; } } } codemaker::ExceptionTree tree; for (sal_uInt16 j = 0; j < m_reader.getMethodExceptionCount(i); ++j) { tree.add( rtl::OUStringToOString( m_reader.getMethodExceptionTypeName(i, j), RTL_TEXTENCODING_UTF8), m_typeMgr); } if (!tree.getRoot()->present) { includes.add("com/sun/star/uno/Exception"); includes.add("com/sun/star/uno/RuntimeException"); includeExceptions(includes, tree.getRoot()); } } } } rtl::OString cppName(translateUnoToCppIdentifier( m_name, "service", isGlobal())); rtl::OString headerDefine(dumpHeaderDefine(o, "HPP")); o << "\n"; includes.dump(o, 0); o << "\n"; if (codemaker::cppumaker::dumpNamespaceOpen(o, m_typeName, false)) { o << "\n"; } o << "\nclass " << cppName << " {\n"; inc(); if (ctors > 0) { rtl::OString fullName(m_typeName.replace('/', '.')); rtl::OString baseName( rtl::OUStringToOString( m_reader.getSuperTypeName(0), RTL_TEXTENCODING_UTF8)); rtl::OString fullBaseName(baseName.replace('/', '.')); rtl::OString scopedBaseName(scopedCppName(baseName)); o << "public:\n"; for (sal_uInt16 i = 0; i < ctors; ++i) { if (isDefaultConstructor(i)) { o << indent() << "static ::com::sun::star::uno::Reference< " << scopedBaseName << " > " << translateUnoToCppIdentifier( "create", "method", ITM_NONGLOBAL, &cppName) << ("(::com::sun::star::uno::Reference<" " ::com::sun::star::uno::XComponentContext > const &" " the_context) {\n"); inc(); o << indent() << "assert(the_context.is());\n" << indent() << "::com::sun::star::uno::Reference< " << scopedBaseName << " > the_instance;\n" << indent() << "try {\n"; inc(); o << indent() << "the_instance = ::com::sun::star::uno::Reference< " << scopedBaseName << (" >(the_context->getServiceManager()->" "createInstanceWithContext(::rtl::OUString(" " \"") << fullName << "\" ), the_context), ::com::sun::star::uno::UNO_QUERY);\n"; dec(); o << indent() << "} catch (::com::sun::star::uno::RuntimeException &) {\n"; inc(); o << indent() << "throw;\n"; dec(); o << indent() << ("} catch (::com::sun::star::uno::Exception &" " the_exception) {\n"); inc(); o << indent() << ("throw ::com::sun::star::uno::DeploymentException(" "::rtl::OUString( " "\"component context fails to supply service ") << fullName << " of type " << fullBaseName << ": \" ) + the_exception.Message, the_context);\n"; dec(); o << indent() << "}\n" << indent() << "if (!the_instance.is()) {\n"; inc(); o << indent() << ("throw ::com::sun::star::uno::DeploymentException(" "::rtl::OUString( " "\"component context fails to supply service ") << fullName << " of type " << fullBaseName << "\" ), the_context);\n"; dec(); o << indent() << "}\n" << indent() << "return the_instance;\n"; dec(); o << indent() << "}\n\n"; } else { o << indent() << "static ::com::sun::star::uno::Reference< " << scopedBaseName << " > " << translateUnoToCppIdentifier( rtl::OUStringToOString( m_reader.getMethodName(i), RTL_TEXTENCODING_UTF8), "method", ITM_NONGLOBAL, &cppName) << ("(::com::sun::star::uno::Reference<" " ::com::sun::star::uno::XComponentContext > const &" " the_context"); sal_uInt16 params = m_reader.getMethodParameterCount(i); bool rest = hasRestParameter(i); for (sal_uInt16 j = 0; j < params; ++j) { o << ", "; rtl::OStringBuffer buf; if ((m_reader.getMethodParameterFlags(i, j) & RT_PARAM_REST) != 0) { buf.append(RTL_CONSTASCII_STRINGPARAM("[]")); } buf.append( rtl::OUStringToOString( m_reader.getMethodParameterTypeName(i, j), RTL_TEXTENCODING_UTF8)); rtl::OString type(buf.makeStringAndClear()); bool byRef = passByReference(type); dumpType(o, type, byRef, byRef); o << " " << translateUnoToCppIdentifier( rtl::OUStringToOString( m_reader.getMethodParameterName(i, j), RTL_TEXTENCODING_UTF8), "param", ITM_NONGLOBAL); } o << ") {\n"; inc(); o << indent() << "assert(the_context.is());\n"; if (!rest && params > 0) { o << indent() << ("::com::sun::star::uno::Sequence<" " ::com::sun::star::uno::Any > the_arguments(") << params << ");\n"; for (sal_uInt16 j = 0; j < params; ++j) { o << indent() << "the_arguments[" << j << "] "; rtl::OString param( translateUnoToCppIdentifier( rtl::OUStringToOString( m_reader.getMethodParameterName(i, j), RTL_TEXTENCODING_UTF8), "param", ITM_NONGLOBAL)); sal_Int32 rank; if (codemaker::UnoType::getSort( codemaker::UnoType::decompose( rtl::OUStringToOString( m_reader.getMethodParameterTypeName( i, j), RTL_TEXTENCODING_UTF8), &rank, 0)) == codemaker::UnoType::SORT_CHAR) { o << "= ::com::sun::star::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() << "::com::sun::star::uno::Reference< " << scopedBaseName << " > the_instance;\n"; codemaker::ExceptionTree tree; sal_uInt16 exceptions = m_reader.getMethodExceptionCount(i); for (sal_uInt16 j = 0; j < exceptions; ++j) { tree.add( rtl::OUStringToOString( m_reader.getMethodExceptionTypeName(i, j), RTL_TEXTENCODING_UTF8), m_typeMgr); } if (!tree.getRoot()->present) { o << indent() << "try {\n"; inc(); } o << indent() << "the_instance = ::com::sun::star::uno::Reference< " << scopedBaseName << (" >(the_context->getServiceManager()->" "createInstanceWithArgumentsAndContext(::rtl::OUString(" " \"") << fullName << "\" ), "; if (rest) { o << translateUnoToCppIdentifier( rtl::OUStringToOString( m_reader.getMethodParameterName(i, 0), RTL_TEXTENCODING_UTF8), "param", ITM_NONGLOBAL); } else if (params == 0) { o << ("::com::sun::star::uno::Sequence<" " ::com::sun::star::uno::Any >()"); } else { o << "the_arguments"; } o << ", the_context), ::com::sun::star::uno::UNO_QUERY);\n"; if (!tree.getRoot()->present) { dec(); o << indent() << ("} catch (::com::sun::star::uno::RuntimeException &)" " {\n"); inc(); o << indent() << "throw;\n"; dec(); dumpCatchClauses(o, tree.getRoot()); o << indent() << ("} catch (::com::sun::star::uno::Exception &" " the_exception) {\n"); inc(); o << indent() << ("throw ::com::sun::star::uno::DeploymentException(" "::rtl::OUString( " "\"component context fails to supply service ") << fullName << " of type " << fullBaseName << ": \" ) + the_exception.Message, the_context);\n"; dec(); o << indent() << "}\n"; } o << indent() << "if (!the_instance.is()) {\n"; inc(); o << indent() << ("throw ::com::sun::star::uno::DeploymentException(" "::rtl::OUString( " "\"component context fails to supply service ") << fullName << " of type " << fullBaseName << "\" ), 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, m_typeName, false)) { o << "\n"; } o << "\n#endif // "<< headerDefine << "\n"; return true; } void ServiceType::addSpecialDependencies() { if (m_reader.getMethodCount() > 0) { OSL_ASSERT(m_reader.getSuperTypeCount() == 1); m_dependencies.add( rtl::OUStringToOString( m_reader.getSuperTypeName(0), RTL_TEXTENCODING_UTF8)); } } bool ServiceType::isDefaultConstructor(sal_uInt16 ctorIndex) const { return m_reader.getMethodName(ctorIndex).isEmpty(); } bool ServiceType::hasRestParameter(sal_uInt16 ctorIndex) const { return m_reader.getMethodParameterCount(ctorIndex) == 1 && ((m_reader.getMethodParameterFlags(ctorIndex, 0) & RT_PARAM_REST) != 0); } void ServiceType::dumpCatchClauses( FileStream & out, codemaker::ExceptionTreeNode const * node) { if (node->present) { out << indent() << "} catch ("; dumpType(out, node->name); out << " &) {\n"; inc(); out << indent() << "throw;\n"; dec(); } else { for (codemaker::ExceptionTreeNode::Children::const_iterator i( node->children.begin()); i != node->children.end(); ++i) { dumpCatchClauses(out, *i); } } } //************************************************************************* // SingletonType //************************************************************************* bool SingletonType::isInterfaceBased() { return (m_typeMgr.getTypeClass( rtl::OUStringToOString( m_reader.getSuperTypeName(0), RTL_TEXTENCODING_UTF8))) == RT_TYPE_INTERFACE; } sal_Bool SingletonType::dumpHxxFile( FileStream & o, codemaker::cppumaker::Includes & includes) throw (CannotDumpException) { rtl::OString cppName(translateUnoToCppIdentifier( m_name, "singleton", isGlobal())); rtl::OString fullName(m_typeName.replace('/', '.')); rtl::OString baseName( rtl::OUStringToOString( m_reader.getSuperTypeName(0), RTL_TEXTENCODING_UTF8)); rtl::OString fullBaseName(baseName.replace('/', '.')); rtl::OString scopedBaseName(scopedCppName(baseName)); rtl::OString headerDefine(dumpHeaderDefine(o, "HPP")); o << "\n"; //TODO: Decide whether the types added to includes should rather be added to // m_dependencies (and thus be generated during dumpDependedTypes): includes.add("com/sun/star/uno/DeploymentException"); includes.add("com/sun/star/uno/XComponentContext"); includes.addCassert(); includes.addAny(); includes.addReference(); includes.addRtlUstringH(); includes.addRtlUstringHxx(); includes.dump(o, 0); o << "\n"; if (codemaker::cppumaker::dumpNamespaceOpen(o, m_typeName, false)) { o << "\n"; } o << "\nclass " << cppName << " {\npublic:\n"; inc(); o << indent() << "static ::com::sun::star::uno::Reference< " << scopedBaseName << " > " << translateUnoToCppIdentifier("get", "method", ITM_NONGLOBAL, &cppName) << ("(::com::sun::star::uno::Reference<" " ::com::sun::star::uno::XComponentContext > const & the_context)" " {\n"); inc(); o << indent() << "assert(the_context.is());\n" << indent() << "::com::sun::star::uno::Reference< " << scopedBaseName << " > instance;\n" << indent() << ("if (!(the_context->getValueByName(" "::rtl::OUString( \"/singletons/") << fullName << "\" )) >>= instance) || !instance.is()) {\n"; inc(); o << indent() << ("throw ::com::sun::star::uno::DeploymentException(" "::rtl::OUString( \"component context" " fails to supply singleton ") << fullName << " of type " << fullBaseName << "\" ), 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, m_typeName, false)) { o << "\n"; } o << "\n#endif // "<< headerDefine << "\n"; return true; } //************************************************************************* // produceType //************************************************************************* bool produceType(const OString& typeName, TypeManager const & typeMgr, codemaker::GeneratedTypeSet & generated, CppuOptions* pOptions) throw( CannotDumpException ) { if (typeName.equals("/") || typeName.equals(typeMgr.getBase()) || TypeManager::isBaseType(typeName) || generated.contains(typeName)) { return true; } sal_Bool bIsExtraType = sal_False; typereg::Reader reader(typeMgr.getTypeReader(typeName, &bIsExtraType)); if (bIsExtraType) { generated.add(typeName); return true; } if (!reader.isValid()) { return false; } RTTypeClass typeClass = reader.getTypeClass(); bool ret = false; switch (typeClass) { case RT_TYPE_INTERFACE: { InterfaceType iType(reader, typeName, typeMgr); ret = iType.dump(pOptions); if (ret) generated.add(typeName); iType.dumpDependedTypes(generated, pOptions); } break; case RT_TYPE_MODULE: { ModuleType mType(reader, typeName, typeMgr); if (mType.hasConstants()) { ret = mType.dump(pOptions); if (ret) generated.add(typeName); } else { generated.add(typeName); ret = true; } } break; case RT_TYPE_STRUCT: { StructureType sType(reader, typeName, typeMgr); ret = sType.dump(pOptions); if (ret) generated.add(typeName); sType.dumpDependedTypes(generated, pOptions); } break; case RT_TYPE_ENUM: { EnumType enType(reader, typeName, typeMgr); ret = enType.dump(pOptions); if (ret) generated.add(typeName); enType.dumpDependedTypes(generated, pOptions); } break; case RT_TYPE_EXCEPTION: { ExceptionType eType(reader, typeName, typeMgr); ret = eType.dump(pOptions); if (ret) generated.add(typeName); eType.dumpDependedTypes(generated, pOptions); } break; case RT_TYPE_TYPEDEF: { TypeDefType tdType(reader, typeName, typeMgr); ret = tdType.dump(pOptions); if (ret) generated.add(typeName); tdType.dumpDependedTypes(generated, pOptions); } break; case RT_TYPE_CONSTANTS: { ConstantsType cType(reader, typeName, typeMgr); if (cType.hasConstants()) { ret = cType.dump(pOptions); if (ret) generated.add(typeName); } else { generated.add(typeName); ret = true; } } break; case RT_TYPE_SERVICE: { ServiceType t(reader, typeName, typeMgr); if (t.isSingleInterfaceBased()) { ret = t.dump(pOptions); if (ret) { generated.add(typeName); t.dumpDependedTypes(generated, pOptions); } } else { ret = true; } } break; case RT_TYPE_SINGLETON: { SingletonType t(reader, typeName, typeMgr); if (t.isInterfaceBased()) { ret = t.dump(pOptions); if (ret) { generated.add(typeName); t.dumpDependedTypes(generated, pOptions); } } else { ret = true; } } break; case RT_TYPE_OBJECT: ret = true; break; default: OSL_ASSERT(false); break; } return ret; } bool produceType(RegistryKey& rTypeKey, bool bIsExtraType, TypeManager const & typeMgr, codemaker::GeneratedTypeSet & generated, CppuOptions* pOptions) throw( CannotDumpException ) { OString typeName = typeMgr.getTypeName(rTypeKey); if (typeName.equals("/") ||typeName.equals(typeMgr.getBase()) || TypeManager::isBaseType(typeName) || generated.contains(typeName)) { return true; } if (bIsExtraType) { generated.add(typeName); return true; } typereg::Reader reader(typeMgr.getTypeReader(rTypeKey)); if (!reader.isValid()) { return false; } RTTypeClass typeClass = reader.getTypeClass(); bool ret = false; switch (typeClass) { case RT_TYPE_INTERFACE: { InterfaceType iType(reader, typeName, typeMgr); ret = iType.dump(pOptions); if (ret) generated.add(typeName); iType.dumpDependedTypes(generated, pOptions); } break; case RT_TYPE_MODULE: { ModuleType mType(reader, typeName, typeMgr); if (mType.hasConstants()) { ret = mType.dump(pOptions); if (ret) generated.add(typeName); } else { generated.add(typeName); ret = true; } } break; case RT_TYPE_STRUCT: { StructureType sType(reader, typeName, typeMgr); ret = sType.dump(pOptions); if (ret) generated.add(typeName); sType.dumpDependedTypes(generated, pOptions); } break; case RT_TYPE_ENUM: { EnumType enType(reader, typeName, typeMgr); ret = enType.dump(pOptions); if (ret) generated.add(typeName); enType.dumpDependedTypes(generated, pOptions); } break; case RT_TYPE_EXCEPTION: { ExceptionType eType(reader, typeName, typeMgr); ret = eType.dump(pOptions); if (ret) generated.add(typeName); eType.dumpDependedTypes(generated, pOptions); } break; case RT_TYPE_TYPEDEF: { TypeDefType tdType(reader, typeName, typeMgr); ret = tdType.dump(pOptions); if (ret) generated.add(typeName); tdType.dumpDependedTypes(generated, pOptions); } break; case RT_TYPE_CONSTANTS: { ConstantsType cType(reader, typeName, typeMgr); if (cType.hasConstants()) { ret = cType.dump(pOptions); if (ret) generated.add(typeName); } else { generated.add(typeName); ret = true; } } break; case RT_TYPE_SERVICE: { ServiceType t(reader, typeName, typeMgr); if (t.isSingleInterfaceBased()) { ret = t.dump(pOptions); if (ret) { generated.add(typeName); t.dumpDependedTypes(generated, pOptions); } } else { ret = true; } } break; case RT_TYPE_SINGLETON: { SingletonType t(reader, typeName, typeMgr); if (t.isInterfaceBased()) { ret = t.dump(pOptions); if (ret) { generated.add(typeName); t.dumpDependedTypes(generated, pOptions); } } else { ret = true; } } break; case RT_TYPE_OBJECT: ret = true; break; default: OSL_ASSERT(false); break; } return ret; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */