Branch libreoffice-24-8-3
[LibreOffice.git] / codemaker / source / cppumaker / cpputype.cxx
bloba2db78363d41b989d96c6e1332f6dc491348c466
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
23 #include <algorithm>
24 #include <cassert>
25 #include <cstdlib>
26 #include <map>
27 #include <set>
28 #include <string_view>
29 #include <memory>
30 #include <utility>
31 #include <vector>
32 #include <iostream>
34 #include <rtl/alloc.h>
35 #include <rtl/ref.hxx>
36 #include <rtl/ustrbuf.hxx>
37 #include <rtl/ustring.hxx>
38 #include <rtl/strbuf.hxx>
39 #include <unoidl/unoidl.hxx>
41 #include <codemaker/commoncpp.hxx>
42 #include <codemaker/exceptiontree.hxx>
43 #include <codemaker/generatedtypeset.hxx>
44 #include <codemaker/typemanager.hxx>
45 #include <codemaker/unotype.hxx>
47 #include "cpputype.hxx"
48 #include "cppuoptions.hxx"
49 #include "dependencies.hxx"
50 #include "dumputils.hxx"
51 #include "includes.hxx"
53 namespace
56 using FileType = codemaker::cppumaker::FileType;
58 bool isBootstrapType(OUString const & name)
60 static char const * const names[] = {
61 "com.sun.star.beans.Property",
62 "com.sun.star.beans.PropertyAttribute",
63 "com.sun.star.beans.PropertyChangeEvent",
64 "com.sun.star.beans.PropertyState",
65 "com.sun.star.beans.PropertyValue",
66 "com.sun.star.beans.XFastPropertySet",
67 "com.sun.star.beans.XMultiPropertySet",
68 "com.sun.star.beans.XPropertiesChangeListener",
69 "com.sun.star.beans.XPropertyAccess",
70 "com.sun.star.beans.XPropertyChangeListener",
71 "com.sun.star.beans.XPropertySet",
72 "com.sun.star.beans.XPropertySetInfo",
73 "com.sun.star.beans.XPropertySetOption",
74 "com.sun.star.beans.XVetoableChangeListener",
75 "com.sun.star.bridge.UnoUrlResolver",
76 "com.sun.star.bridge.XUnoUrlResolver",
77 "com.sun.star.connection.SocketPermission",
78 "com.sun.star.container.XElementAccess",
79 "com.sun.star.container.XEnumeration",
80 "com.sun.star.container.XEnumerationAccess",
81 "com.sun.star.container.XHierarchicalNameAccess",
82 "com.sun.star.container.XNameAccess",
83 "com.sun.star.container.XNameContainer",
84 "com.sun.star.container.XNameReplace",
85 "com.sun.star.container.XSet",
86 "com.sun.star.io.FilePermission",
87 "com.sun.star.io.IOException",
88 "com.sun.star.lang.DisposedException",
89 "com.sun.star.lang.EventObject",
90 "com.sun.star.lang.WrappedTargetRuntimeException",
91 "com.sun.star.lang.XComponent",
92 "com.sun.star.lang.XEventListener",
93 "com.sun.star.lang.XInitialization",
94 "com.sun.star.lang.XMultiComponentFactory",
95 "com.sun.star.lang.XMultiServiceFactory",
96 "com.sun.star.lang.XServiceInfo",
97 "com.sun.star.lang.XSingleComponentFactory",
98 "com.sun.star.lang.XSingleServiceFactory",
99 "com.sun.star.lang.XTypeProvider",
100 "com.sun.star.loader.XImplementationLoader",
101 "com.sun.star.reflection.FieldAccessMode",
102 "com.sun.star.reflection.MethodMode",
103 "com.sun.star.reflection.ParamInfo",
104 "com.sun.star.reflection.ParamMode",
105 "com.sun.star.reflection.TypeDescriptionSearchDepth",
106 "com.sun.star.reflection.XCompoundTypeDescription",
107 "com.sun.star.reflection.XEnumTypeDescription",
108 "com.sun.star.reflection.XIdlArray",
109 "com.sun.star.reflection.XIdlClass",
110 "com.sun.star.reflection.XIdlField",
111 "com.sun.star.reflection.XIdlField2",
112 "com.sun.star.reflection.XIdlMethod",
113 "com.sun.star.reflection.XIdlReflection",
114 "com.sun.star.reflection.XIndirectTypeDescription",
115 "com.sun.star.reflection.XInterfaceAttributeTypeDescription",
116 "com.sun.star.reflection.XInterfaceAttributeTypeDescription2",
117 "com.sun.star.reflection.XInterfaceMemberTypeDescription",
118 "com.sun.star.reflection.XInterfaceMethodTypeDescription",
119 "com.sun.star.reflection.XInterfaceTypeDescription",
120 "com.sun.star.reflection.XInterfaceTypeDescription2",
121 "com.sun.star.reflection.XMethodParameter",
122 "com.sun.star.reflection.XStructTypeDescription",
123 "com.sun.star.reflection.XTypeDescription",
124 "com.sun.star.reflection.XTypeDescriptionEnumeration",
125 "com.sun.star.reflection.XTypeDescriptionEnumerationAccess",
126 "com.sun.star.registry.RegistryKeyType",
127 "com.sun.star.registry.RegistryValueType",
128 "com.sun.star.registry.XImplementationRegistration",
129 "com.sun.star.registry.XRegistryKey",
130 "com.sun.star.registry.XSimpleRegistry",
131 "com.sun.star.security.RuntimePermission",
132 "com.sun.star.security.XAccessControlContext",
133 "com.sun.star.security.XAccessController",
134 "com.sun.star.security.XAction",
135 "com.sun.star.uno.DeploymentException",
136 "com.sun.star.uno.RuntimeException",
137 "com.sun.star.uno.TypeClass",
138 "com.sun.star.uno.Uik",
139 "com.sun.star.uno.XAdapter",
140 "com.sun.star.uno.XAggregation",
141 "com.sun.star.uno.XComponentContext",
142 "com.sun.star.uno.XCurrentContext",
143 "com.sun.star.uno.XInterface",
144 "com.sun.star.uno.XReference",
145 "com.sun.star.uno.XUnloadingPreference",
146 "com.sun.star.uno.XWeak",
147 "com.sun.star.util.XMacroExpander" };
148 // cf. cppuhelper/unotypes/Makefile UNOTYPES (plus missing dependencies)
149 auto const pred = [&name](const char* aName) {
150 return name.equalsAscii(aName);
152 return std::any_of(std::begin(names), std::end(names), pred);
155 OString getFileExtension(FileType eFileType)
157 switch(eFileType)
159 default:
160 case FileType::HDL: return ".hdl"_ostr;
161 case FileType::HPP: return ".hpp"_ostr;
165 class CppuType
167 public:
168 CppuType(OUString name, rtl::Reference< TypeManager > const & typeMgr);
170 virtual ~CppuType() {}
172 CppuType(const CppuType&) = delete;
173 const CppuType& operator=(const CppuType&) = delete;
175 void dump(CppuOptions const & options);
177 void dumpFile(
178 std::u16string_view uri, std::u16string_view name, FileType eFileType,
179 CppuOptions const & options);
181 void dumpDependedTypes(
182 codemaker::GeneratedTypeSet & generated, CppuOptions const & options) const;
184 virtual void dumpHdlFile(
185 FileStream & out, codemaker::cppumaker::Includes & includes) {
186 dumpHFileContent(out, includes);
189 virtual void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) = 0;
191 OUString dumpHeaderDefine(FileStream& o, std::u16string_view extension) const;
193 void dumpGetCppuType(FileStream & out);
195 virtual void dumpLightGetCppuType(FileStream & out);
197 virtual void dumpNormalGetCppuType(FileStream &) {
198 assert(false); // this cannot happen
201 virtual void dumpComprehensiveGetCppuType(FileStream &) {
202 assert(false); // this cannot happen
205 void dumpType(
206 FileStream & out, std::u16string_view name, bool isConst = false,
207 bool isRef = false, bool native = false, bool cppuUnoType = false)
208 const;
210 OUString getTypeClass(OUString const & name, bool cStyle = false);
212 void dumpCppuGetType(
213 FileStream & out, std::u16string_view name, OUString const * ownName = nullptr) const;
215 sal_uInt32 getInheritedMemberCount();
217 void inc(sal_Int32 num=4);
218 void dec(sal_Int32 num=4);
219 OUString indent() const;
220 protected:
221 virtual sal_uInt32 checkInheritedMemberCount() const {
222 assert(false); // this cannot happen
223 return 0;
226 bool passByReference(OUString const & name) const;
228 bool canBeWarnUnused(OUString const & name) const;
229 bool canBeWarnUnused(OUString const & name, int depth) const;
231 OUString resolveOuterTypedefs(OUString const & name) const;
233 OUString resolveAllTypedefs(std::u16string_view name) const;
235 codemaker::cpp::IdentifierTranslationMode isGlobal() const;
237 virtual void dumpDeclaration(FileStream &) {
238 assert(false); // this cannot happen
241 virtual void dumpFiles(OUString const & uri, CppuOptions const & options);
243 virtual void addLightGetCppuTypeIncludes(
244 codemaker::cppumaker::Includes & includes) const;
246 virtual void addNormalGetCppuTypeIncludes(
247 codemaker::cppumaker::Includes & includes) const;
249 virtual void addComprehensiveGetCppuTypeIncludes(
250 codemaker::cppumaker::Includes & includes) const;
252 virtual bool isPolymorphic() const;
254 virtual void dumpTemplateHead(FileStream &) const {}
256 virtual void dumpTemplateParameters(FileStream &) const {}
258 void dumpGetCppuTypePreamble(FileStream & out);
260 void dumpGetCppuTypePostamble(FileStream & out);
262 void addDefaultHIncludes(codemaker::cppumaker::Includes & includes) const;
263 void addDefaultHxxIncludes(codemaker::cppumaker::Includes & includes) const;
265 void dumpInitializer(
266 FileStream & out, bool parameterized, std::u16string_view name) const;
268 void dumpHFileContent(
269 FileStream & out, codemaker::cppumaker::Includes & includes);
271 protected:
272 sal_uInt32 m_inheritedMemberCount;
274 bool m_cppuTypeLeak;
275 bool m_cppuTypeDynamic;
276 sal_Int32 m_indentLength;
277 OUString name_;
278 OUString id_;
279 rtl::Reference< TypeManager > m_typeMgr;
280 codemaker::cppumaker::Dependencies m_dependencies;
282 private:
283 void addGetCppuTypeIncludes(codemaker::cppumaker::Includes & includes)
284 const;
287 CppuType::CppuType(
288 OUString name, rtl::Reference< TypeManager > const & typeMgr):
289 m_inheritedMemberCount(0)
290 , m_cppuTypeLeak(false)
291 , m_cppuTypeDynamic(true)
292 , m_indentLength(0)
293 , name_(std::move(name))
294 , id_(name_.copy(name_.lastIndexOf('.') + 1))
295 , m_typeMgr(typeMgr)
296 , m_dependencies(typeMgr, name_)
299 void CppuType::addGetCppuTypeIncludes(codemaker::cppumaker::Includes & includes)
300 const
302 if (name_ == "com.sun.star.uno.XInterface"
303 || name_ == "com.sun.star.uno.Exception") {
304 includes.addType();
305 includes.addCppuUnotypeHxx();
306 includes.addSalTypesH();
307 includes.addTypelibTypeclassH();
308 includes.addTypelibTypedescriptionH();
309 } else if (m_cppuTypeLeak) {
310 addLightGetCppuTypeIncludes(includes);
311 } else if (m_cppuTypeDynamic) {
312 addNormalGetCppuTypeIncludes(includes);
313 } else {
314 addComprehensiveGetCppuTypeIncludes(includes);
318 void CppuType::dumpFiles(OUString const & uri, CppuOptions const & options)
320 dumpFile(uri, name_, FileType::HDL, options);
321 dumpFile(uri, name_, FileType::HPP, options);
324 void CppuType::addLightGetCppuTypeIncludes(
325 codemaker::cppumaker::Includes & includes) const
327 //TODO: Determine what is really needed, instead of relying on
328 // addDefaultHxxIncludes
329 includes.addCppuUnotypeHxx();
332 void CppuType::addNormalGetCppuTypeIncludes(
333 codemaker::cppumaker::Includes & includes) const
335 //TODO: Determine what is really needed, instead of relying on
336 // addDefaultHxxIncludes
337 includes.addCppuUnotypeHxx();
340 void CppuType::addComprehensiveGetCppuTypeIncludes(
341 codemaker::cppumaker::Includes & includes) const
343 //TODO: Determine what is really needed, instead of relying on
344 // addDefaultHxxIncludes
345 includes.addCppuUnotypeHxx();
348 bool CppuType::isPolymorphic() const
350 return false;
353 void CppuType::dumpGetCppuTypePreamble(FileStream & out)
355 if (isPolymorphic()) {
356 out << "namespace cppu {\n\n";
357 dumpTemplateHead(out);
358 out << "class UnoType< ";
359 dumpType(out, name_);
360 dumpTemplateParameters(out);
361 out << " > {\npublic:\n";
362 inc();
363 out << indent()
364 << "static inline ::css::uno::Type const & get() {\n";
365 } else {
366 if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) {
367 out << "\n\n";
369 out << ("inline ::css::uno::Type const &"
370 " cppu_detail_getUnoType(SAL_UNUSED_PARAMETER ");
371 dumpType(out, name_, false, false, true);
372 out << " const *) {\n";
374 inc();
377 void CppuType::dumpGetCppuTypePostamble(FileStream & out)
379 dec();
380 if (isPolymorphic()) {
381 out << indent() << "}\n\nprivate:\n"
382 << indent() << "UnoType(UnoType &); // not defined\n"
383 << indent() << "~UnoType(); // not defined\n"
384 << indent()
385 << "void operator =(UnoType); // not defined\n};\n\n}\n\n";
386 } else {
387 out << "}\n\n";
388 if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) {
389 out << "\n\n";
392 dumpTemplateHead(out);
393 out << ("SAL_DEPRECATED(\"use cppu::UnoType\") inline ::css::uno::Type const & SAL_CALL"
394 " getCppuType(SAL_UNUSED_PARAMETER ");
395 dumpType(out, name_);
396 dumpTemplateParameters(out);
397 out << " const *) {\n";
398 inc();
399 out << indent() << "return ::cppu::UnoType< ";
400 dumpType(out, name_);
401 dumpTemplateParameters(out);
402 out << " >::get();\n";
403 dec();
404 out << indent() << "}\n";
407 void CppuType::dump(CppuOptions const & options)
409 if (isBootstrapType(name_)) {
410 m_cppuTypeDynamic = false;
411 } else {
412 // -CS was used as an undocumented option to generate static getCppuType
413 // functions; since the introduction of cppu::UnoType this no longer is
414 // meaningful (getCppuType is just a forward to cppu::UnoType::get now),
415 // and -CS is handled the same way as -C now:
416 if (options.isValid("-L"_ostr))
417 m_cppuTypeLeak = true;
418 if (options.isValid("-C"_ostr) || options.isValid("-CS"_ostr))
419 m_cppuTypeDynamic = false;
421 dumpFiles(
422 options.isValid("-O"_ostr) ? b2u(options.getOption("-O"_ostr)) : u""_ustr, options);
425 void CppuType::dumpFile(
426 std::u16string_view uri, std::u16string_view name, FileType eFileType,
427 CppuOptions const & options)
429 OUString fileUri(
430 b2u(createFileNameFromType(
431 u2b(uri), u2b(name), getFileExtension(eFileType))));
432 if (fileUri.isEmpty()) {
433 throw CannotDumpException(OUString::Concat("empty target URI for entity ") + name);
435 bool exists = fileExists(u2b(fileUri));
436 if (exists && options.isValid("-G"_ostr)) {
437 return;
439 FileStream out;
440 out.createTempFile(getTempDir(u2b(fileUri)));
441 OUString tmpUri(b2u(out.getName()));
442 if(!out.isValid()) {
443 throw CannotDumpException("cannot open " + tmpUri + " for writing");
445 codemaker::cppumaker::Includes includes(m_typeMgr, m_dependencies, eFileType);
446 try {
447 switch(eFileType)
449 case FileType::HPP:
450 addGetCppuTypeIncludes(includes);
451 dumpHppFile(out, includes);
452 break;
453 case FileType::HDL:
454 dumpHdlFile(out, includes);
455 break;
457 } catch (...) {
458 out.close();
459 // Remove existing type file if something goes wrong to ensure
460 // consistency:
461 if (fileExists(u2b(fileUri))) {
462 removeTypeFile(u2b(fileUri));
464 removeTypeFile(u2b(tmpUri));
465 throw;
467 out.close();
468 (void)makeValidTypeFile(
469 u2b(fileUri), u2b(tmpUri), exists && options.isValid("-Gc"_ostr));
472 void CppuType::dumpDependedTypes(
473 codemaker::GeneratedTypeSet & generated, CppuOptions const & options) const
475 if (!options.isValid("-nD"_ostr)) {
476 codemaker::cppumaker::Dependencies::Map const & map
477 = m_dependencies.getMap();
478 for (const auto& entry : map) {
479 produce(entry.first, m_typeMgr, generated, options);
484 OUString CppuType::dumpHeaderDefine(
485 FileStream & out, std::u16string_view extension) const
487 OUString def(
488 "INCLUDED_" + name_.replace('.', '_').toAsciiUpperCase() + "_"
489 + extension);
490 out << "#ifndef " << def << "\n#define " << def << "\n";
491 return def;
494 void CppuType::addDefaultHIncludes(codemaker::cppumaker::Includes & includes)
495 const
497 //TODO: Only include what is really needed
498 includes.addCppuMacrosHxx();
499 if (m_typeMgr->getSort(name_)
500 == codemaker::UnoType::Sort::Interface) {
501 includes.addReference();
505 void CppuType::addDefaultHxxIncludes(codemaker::cppumaker::Includes & includes)
506 const
508 //TODO: Only include what is really needed
509 includes.addType();
510 if (m_typeMgr->getSort(name_)
511 == codemaker::UnoType::Sort::Interface) {
512 includes.addReference();
516 void CppuType::dumpInitializer(
517 FileStream & out, bool parameterized, std::u16string_view name) const
519 out << "(";
520 if (!parameterized) {
521 sal_Int32 k;
522 std::vector< OString > args;
523 OUString n(
524 b2u(codemaker::UnoType::decompose(
525 u2b(resolveAllTypedefs(name)), &k, &args)));
526 if (k == 0) {
527 rtl::Reference< unoidl::Entity > ent;
528 switch (m_typeMgr->getSort(n, &ent)) {
529 case codemaker::UnoType::Sort::Boolean:
530 out << "false";
531 break;
532 case codemaker::UnoType::Sort::Byte:
533 case codemaker::UnoType::Sort::Short:
534 case codemaker::UnoType::Sort::UnsignedShort:
535 case codemaker::UnoType::Sort::Long:
536 case codemaker::UnoType::Sort::UnsignedLong:
537 case codemaker::UnoType::Sort::Hyper:
538 case codemaker::UnoType::Sort::UnsignedHyper:
539 case codemaker::UnoType::Sort::Float:
540 case codemaker::UnoType::Sort::Double:
541 case codemaker::UnoType::Sort::Char:
542 out << "0";
543 break;
544 case codemaker::UnoType::Sort::Enum:
545 out << codemaker::cpp::scopedCppName(u2b(n)) << "_"
546 << (dynamic_cast<unoidl::EnumTypeEntity&>(*ent).
547 getMembers()[0].name);
548 break;
549 case codemaker::UnoType::Sort::String:
550 case codemaker::UnoType::Sort::Type:
551 case codemaker::UnoType::Sort::Any:
552 case codemaker::UnoType::Sort::PlainStruct:
553 case codemaker::UnoType::Sort::PolymorphicStructTemplate:
554 case codemaker::UnoType::Sort::Interface:
555 break;
556 default:
557 throw CannotDumpException(
558 OUString::Concat("unexpected entity \"") + name
559 + "\" in call to CppuType::dumpInitializer");
563 out << ")";
566 void CppuType::dumpHFileContent(
567 FileStream & out, codemaker::cppumaker::Includes & includes)
569 addDefaultHIncludes(includes);
570 dumpHeaderDefine(out, u"HDL");
571 out << "\n";
572 includes.dump(out, nullptr, false);
573 // 'exceptions = false' would be wrong for services/singletons, but
574 // those don't dump .hdl files anyway
575 out << ("\nnamespace com { namespace sun { namespace star { namespace uno"
576 " { class Type; } } } }\n\n");
577 if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) {
578 out << "\n";
580 dumpDeclaration(out);
581 if (!(name_ == "com.sun.star.uno.XInterface"
582 || name_ == "com.sun.star.uno.Exception"
583 || isPolymorphic())) {
584 out << "\n" << indent()
585 << ("inline ::css::uno::Type const &"
586 " cppu_detail_getUnoType(SAL_UNUSED_PARAMETER ");
587 dumpType(out, name_, false, false, true);
588 out << " const *);\n";
590 if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) {
591 out << "\n";
593 out << "\n";
594 dumpTemplateHead(out);
595 out << "SAL_DEPRECATED(\"use cppu::UnoType\") inline ::css::uno::Type const & SAL_CALL getCppuType(";
596 dumpType(out, name_, true);
597 dumpTemplateParameters(out);
598 out << " *);\n\n#endif\n";
601 void CppuType::dumpGetCppuType(FileStream & out)
603 if (name_ == "com.sun.star.uno.XInterface") {
604 out << indent()
605 << ("SAL_DEPRECATED(\"use cppu::UnoType\") inline ::css::uno::Type const & SAL_CALL"
606 " getCppuType(SAL_UNUSED_PARAMETER ");
607 dumpType(out, name_, true);
608 out << " *) {\n";
609 inc();
610 out << indent()
611 << ("return ::cppu::UnoType< ::css::uno::XInterface"
612 " >::get();\n");
613 dec();
614 out << indent() << "}\n";
615 } else if (name_ == "com.sun.star.uno.Exception") {
616 out << indent()
617 << ("SAL_DEPRECATED(\"use cppu::UnoType\") inline ::css::uno::Type const & SAL_CALL"
618 " getCppuType(SAL_UNUSED_PARAMETER ");
619 dumpType(out, name_, true);
620 out << " *) {\n";
621 inc();
622 out << indent()
623 << ("return ::cppu::UnoType< ::css::uno::Exception"
624 " >::get();\n");
625 dec();
626 out << indent() << "}\n";
627 } else if (m_cppuTypeLeak) {
628 dumpLightGetCppuType(out);
629 } else if (m_cppuTypeDynamic) {
630 dumpNormalGetCppuType(out);
631 } else {
632 dumpComprehensiveGetCppuType(out);
636 void CppuType::dumpLightGetCppuType(FileStream & out)
638 dumpGetCppuTypePreamble(out);
639 out << indent()
640 << "static typelib_TypeDescriptionReference * the_type = 0;\n"
641 << indent() << "if ( !the_type )\n" << indent() << "{\n";
642 inc();
643 out << indent() << "typelib_static_type_init( &the_type, "
644 << getTypeClass(name_, true) << ", \"" << name_ << "\" );\n";
645 dec();
646 out << indent() << "}\n" << indent()
647 << ("return * reinterpret_cast< ::css::uno::Type * >("
648 " &the_type );\n");
649 dumpGetCppuTypePostamble(out);
652 codemaker::cpp::IdentifierTranslationMode CppuType::isGlobal() const
654 return name_.indexOf('.') == -1
655 ? codemaker::cpp::IdentifierTranslationMode::Global : codemaker::cpp::IdentifierTranslationMode::NonGlobal;
658 sal_uInt32 CppuType::getInheritedMemberCount()
660 if (m_inheritedMemberCount == 0) {
661 m_inheritedMemberCount = checkInheritedMemberCount();
664 return m_inheritedMemberCount;
667 OUString CppuType::getTypeClass(OUString const & name, bool cStyle)
669 rtl::Reference< unoidl::Entity > ent;
670 switch (m_typeMgr->getSort(name, &ent)) {
671 case codemaker::UnoType::Sort::Void:
672 return cStyle
673 ? u"typelib_TypeClass_VOID"_ustr
674 : u"::css::uno::TypeClass_VOID"_ustr;
675 case codemaker::UnoType::Sort::Boolean:
676 return cStyle
677 ? u"typelib_TypeClass_BOOLEAN"_ustr
678 : u"::css::uno::TypeClass_BOOLEAN"_ustr;
679 case codemaker::UnoType::Sort::Byte:
680 return cStyle
681 ? u"typelib_TypeClass_BYTE"_ustr
682 : u"::css::uno::TypeClass_BYTE"_ustr;
683 case codemaker::UnoType::Sort::Short:
684 return cStyle
685 ? u"typelib_TypeClass_SHORT"_ustr
686 : u"::css::uno::TypeClass_SHORT"_ustr;
687 case codemaker::UnoType::Sort::UnsignedShort:
688 return cStyle
689 ? u"typelib_TypeClass_UNSIGNED_SHORT"_ustr
690 : u"::css::uno::TypeClass_UNSIGNED_SHORT"_ustr;
691 case codemaker::UnoType::Sort::Long:
692 return cStyle
693 ? u"typelib_TypeClass_LONG"_ustr
694 : u"::css::uno::TypeClass_LONG"_ustr;
695 case codemaker::UnoType::Sort::UnsignedLong:
696 return cStyle
697 ? u"typelib_TypeClass_UNSIGNED_LONG"_ustr
698 : u"::css::uno::TypeClass_UNSIGNED_LONG"_ustr;
699 case codemaker::UnoType::Sort::Hyper:
700 return cStyle
701 ? u"typelib_TypeClass_HYPER"_ustr
702 : u"::css::uno::TypeClass_HYPER"_ustr;
703 case codemaker::UnoType::Sort::UnsignedHyper:
704 return cStyle
705 ? u"typelib_TypeClass_UNSIGNED_HYPER"_ustr
706 : u"::css::uno::TypeClass_UNSIGNED_HYPER"_ustr;
707 case codemaker::UnoType::Sort::Float:
708 return cStyle
709 ? u"typelib_TypeClass_FLOAT"_ustr
710 : u"::css::uno::TypeClass_FLOAT"_ustr;
711 case codemaker::UnoType::Sort::Double:
712 return cStyle
713 ? u"typelib_TypeClass_DOUBLE"_ustr
714 : u"::css::uno::TypeClass_DOUBLE"_ustr;
715 case codemaker::UnoType::Sort::Char:
716 return cStyle
717 ? u"typelib_TypeClass_CHAR"_ustr
718 : u"::css::uno::TypeClass_CHAR"_ustr;
719 case codemaker::UnoType::Sort::String:
720 return cStyle
721 ? u"typelib_TypeClass_STRING"_ustr
722 : u"::css::uno::TypeClass_STRING"_ustr;
723 case codemaker::UnoType::Sort::Type:
724 return cStyle
725 ? u"typelib_TypeClass_TYPE"_ustr
726 : u"::css::uno::TypeClass_TYPE"_ustr;
727 case codemaker::UnoType::Sort::Any:
728 return cStyle
729 ? u"typelib_TypeClass_ANY"_ustr
730 : u"::css::uno::TypeClass_ANY"_ustr;
731 case codemaker::UnoType::Sort::Sequence:
732 return cStyle
733 ? u"typelib_TypeClass_SEQUENCE"_ustr
734 : u"::css::uno::TypeClass_SEQUENCE"_ustr;
735 case codemaker::UnoType::Sort::Enum:
736 return cStyle
737 ? u"typelib_TypeClass_ENUM"_ustr
738 : u"::css::uno::TypeClass_ENUM"_ustr;
739 case codemaker::UnoType::Sort::PlainStruct:
740 case codemaker::UnoType::Sort::PolymorphicStructTemplate:
741 case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
742 return cStyle
743 ? u"typelib_TypeClass_STRUCT"_ustr
744 : u"::css::uno::TypeClass_STRUCT"_ustr;
745 case codemaker::UnoType::Sort::Exception:
746 return cStyle
747 ? u"typelib_TypeClass_EXCEPTION"_ustr
748 : u"::css::uno::TypeClass_EXCEPTION"_ustr;
749 case codemaker::UnoType::Sort::Interface:
750 return cStyle
751 ? u"typelib_TypeClass_INTERFACE"_ustr
752 : u"::css::uno::TypeClass_INTERFACE"_ustr;
753 case codemaker::UnoType::Sort::Typedef:
754 return getTypeClass(dynamic_cast<unoidl::TypedefEntity&>(*ent).getType(), cStyle);
755 default:
756 for (;;) {
757 std::abort();
762 void CppuType::dumpType(
763 FileStream & out, std::u16string_view name, bool isConst, bool isRef,
764 bool native, bool cppuUnoType) const
766 sal_Int32 k;
767 std::vector< OString > args;
768 OUString n(
769 b2u(codemaker::UnoType::decompose(
770 u2b(resolveAllTypedefs(name)), &k, &args)));
771 if (isConst) {
772 out << "const ";
774 for (sal_Int32 i = 0; i != k; ++i) {
775 out << (cppuUnoType
776 ? "::cppu::UnoSequenceType" : "::css::uno::Sequence")
777 << "< ";
779 switch (m_typeMgr->getSort(n)) {
780 case codemaker::UnoType::Sort::Void:
781 out << "void";
782 break;
783 case codemaker::UnoType::Sort::Boolean:
784 out << "::sal_Bool";
785 break;
786 case codemaker::UnoType::Sort::Byte:
787 out << "::sal_Int8";
788 break;
789 case codemaker::UnoType::Sort::Short:
790 out << "::sal_Int16";
791 break;
792 case codemaker::UnoType::Sort::UnsignedShort:
793 out << (cppuUnoType ? "::cppu::UnoUnsignedShortType" : "::sal_uInt16");
794 break;
795 case codemaker::UnoType::Sort::Long:
796 out << "::sal_Int32";
797 break;
798 case codemaker::UnoType::Sort::UnsignedLong:
799 out << "::sal_uInt32";
800 break;
801 case codemaker::UnoType::Sort::Hyper:
802 out << "::sal_Int64";
803 break;
804 case codemaker::UnoType::Sort::UnsignedHyper:
805 out << "::sal_uInt64";
806 break;
807 case codemaker::UnoType::Sort::Float:
808 out << "float";
809 break;
810 case codemaker::UnoType::Sort::Double:
811 out << "double";
812 break;
813 case codemaker::UnoType::Sort::Char:
814 out << (cppuUnoType ? "::cppu::UnoCharType" : "::sal_Unicode");
815 break;
816 case codemaker::UnoType::Sort::String:
817 out << "::rtl::OUString";
818 break;
819 case codemaker::UnoType::Sort::Type:
820 out << "::css::uno::Type";
821 break;
822 case codemaker::UnoType::Sort::Any:
823 out << "::css::uno::Any";
824 break;
825 case codemaker::UnoType::Sort::Enum:
826 case codemaker::UnoType::Sort::PlainStruct:
827 case codemaker::UnoType::Sort::Exception:
828 out << codemaker::cpp::scopedCppName(u2b(n));
829 break;
830 case codemaker::UnoType::Sort::PolymorphicStructTemplate:
831 out << codemaker::cpp::scopedCppName(u2b(n));
832 if (!args.empty()) {
833 out << "< ";
834 for (std::vector< OString >::iterator i(args.begin());
835 i != args.end(); ++i) {
836 if (i != args.begin()) {
837 out << ", ";
839 dumpType(out, b2u(*i));
841 out << " >";
843 break;
844 case codemaker::UnoType::Sort::Interface:
845 if (!native) {
846 out << "::css::uno::Reference< ";
848 out << codemaker::cpp::scopedCppName(u2b(n));
849 if (!native) {
850 out << " >";
852 break;
853 default:
854 throw CannotDumpException(
855 OUString::Concat("unexpected entity \"") + name + "\" in call to CppuType::dumpType");
857 for (sal_Int32 i = 0; i != k; ++i) {
858 out << " >";
860 if (isRef) {
861 out << "&";
865 void CppuType::dumpCppuGetType(
866 FileStream & out, std::u16string_view name, OUString const * ownName) const
868 //TODO: What are these calls good for?
869 OUString nucleus;
870 sal_Int32 rank;
871 codemaker::UnoType::Sort sort = m_typeMgr->decompose(
872 name, true, &nucleus, &rank, nullptr, nullptr);
873 switch (rank == 0 ? sort : codemaker::UnoType::Sort::Sequence) {
874 case codemaker::UnoType::Sort::Void:
875 case codemaker::UnoType::Sort::Boolean:
876 case codemaker::UnoType::Sort::Byte:
877 case codemaker::UnoType::Sort::Short:
878 case codemaker::UnoType::Sort::UnsignedShort:
879 case codemaker::UnoType::Sort::Long:
880 case codemaker::UnoType::Sort::UnsignedLong:
881 case codemaker::UnoType::Sort::Hyper:
882 case codemaker::UnoType::Sort::UnsignedHyper:
883 case codemaker::UnoType::Sort::Float:
884 case codemaker::UnoType::Sort::Double:
885 case codemaker::UnoType::Sort::Char:
886 case codemaker::UnoType::Sort::String:
887 case codemaker::UnoType::Sort::Type:
888 case codemaker::UnoType::Sort::Any:
889 break;
890 case codemaker::UnoType::Sort::Sequence:
891 case codemaker::UnoType::Sort::Enum:
892 case codemaker::UnoType::Sort::PlainStruct:
893 case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
894 case codemaker::UnoType::Sort::Exception:
895 case codemaker::UnoType::Sort::Interface:
896 // Take care of recursion like struct S { sequence<S> x; }:
897 if (ownName == nullptr || nucleus != *ownName) {
898 out << indent() << "::cppu::UnoType< ";
899 dumpType(out, name, false, false, false, true);
900 out << " >::get();\n";
902 break;
903 case codemaker::UnoType::Sort::Typedef:
904 for (;;) std::abort(); // this cannot happen
905 default:
906 throw CannotDumpException(
907 OUString::Concat("unexpected entity \"") + name
908 + "\" in call to CppuType::dumpCppuGetType");
912 bool CppuType::passByReference(OUString const & name) const
914 switch (m_typeMgr->getSort(resolveOuterTypedefs(name))) {
915 case codemaker::UnoType::Sort::Boolean:
916 case codemaker::UnoType::Sort::Byte:
917 case codemaker::UnoType::Sort::Short:
918 case codemaker::UnoType::Sort::UnsignedShort:
919 case codemaker::UnoType::Sort::Long:
920 case codemaker::UnoType::Sort::UnsignedLong:
921 case codemaker::UnoType::Sort::Hyper:
922 case codemaker::UnoType::Sort::UnsignedHyper:
923 case codemaker::UnoType::Sort::Float:
924 case codemaker::UnoType::Sort::Double:
925 case codemaker::UnoType::Sort::Char:
926 case codemaker::UnoType::Sort::Enum:
927 return false;
928 case codemaker::UnoType::Sort::String:
929 case codemaker::UnoType::Sort::Type:
930 case codemaker::UnoType::Sort::Any:
931 case codemaker::UnoType::Sort::Sequence:
932 case codemaker::UnoType::Sort::PlainStruct:
933 case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
934 case codemaker::UnoType::Sort::Interface:
935 return true;
936 default:
937 throw CannotDumpException(
938 "unexpected entity \"" + name
939 + "\" in call to CppuType::passByReference");
943 bool CppuType::canBeWarnUnused(OUString const & name) const
945 return canBeWarnUnused(name, 0);
947 bool CppuType::canBeWarnUnused(OUString const & name, int depth) const
949 // prevent infinite recursion and blowing the stack
950 if (depth > 10)
951 return false;
952 OUString aResolvedName = resolveOuterTypedefs(name);
953 switch (m_typeMgr->getSort(aResolvedName)) {
954 case codemaker::UnoType::Sort::Boolean:
955 case codemaker::UnoType::Sort::Byte:
956 case codemaker::UnoType::Sort::Short:
957 case codemaker::UnoType::Sort::UnsignedShort:
958 case codemaker::UnoType::Sort::Long:
959 case codemaker::UnoType::Sort::UnsignedLong:
960 case codemaker::UnoType::Sort::Hyper:
961 case codemaker::UnoType::Sort::UnsignedHyper:
962 case codemaker::UnoType::Sort::Float:
963 case codemaker::UnoType::Sort::Double:
964 case codemaker::UnoType::Sort::Char:
965 case codemaker::UnoType::Sort::Enum:
966 case codemaker::UnoType::Sort::String:
967 case codemaker::UnoType::Sort::Type:
968 return true;
969 case codemaker::UnoType::Sort::PlainStruct: {
970 rtl::Reference< unoidl::Entity > ent;
971 m_typeMgr->getSort(aResolvedName, &ent);
972 rtl::Reference< unoidl::PlainStructTypeEntity > ent2(
973 dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get()));
974 if (!ent2->getDirectBase().isEmpty() && !canBeWarnUnused(ent2->getDirectBase(), depth+1))
975 return false;
976 for ( const unoidl::PlainStructTypeEntity::Member& rMember : ent2->getDirectMembers()) {
977 if (!canBeWarnUnused(rMember.type, depth+1))
978 return false;
980 return true;
982 case codemaker::UnoType::Sort::Sequence: {
983 OUString aInnerType = aResolvedName.copy(2);
984 return canBeWarnUnused(aInnerType, depth+1);
986 case codemaker::UnoType::Sort::Any:
987 case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
988 case codemaker::UnoType::Sort::Interface:
989 return false;
990 default:
991 throw CannotDumpException(
992 "unexpected entity \"" + name
993 + "\" in call to CppuType::canBeWarnUnused");
997 OUString CppuType::resolveOuterTypedefs(OUString const & name) const
999 for (OUString n(name);;) {
1000 rtl::Reference< unoidl::Entity > ent;
1001 if (m_typeMgr->getSort(n, &ent) != codemaker::UnoType::Sort::Typedef) {
1002 return n;
1004 n = dynamic_cast<unoidl::TypedefEntity&>(*ent).getType();
1008 OUString CppuType::resolveAllTypedefs(std::u16string_view name) const
1010 sal_Int32 k1;
1011 OUString n(b2u(codemaker::UnoType::decompose(u2b(name), &k1)));
1012 for (;;) {
1013 rtl::Reference< unoidl::Entity > ent;
1014 if (m_typeMgr->getSort(n, &ent) != codemaker::UnoType::Sort::Typedef) {
1015 break;
1017 sal_Int32 k2;
1018 n = b2u(codemaker::UnoType::decompose(
1019 u2b(dynamic_cast<unoidl::TypedefEntity&>(*ent).getType()), &k2));
1020 k1 += k2; //TODO: overflow
1022 OUStringBuffer b(k1*2 + n.getLength());
1023 for (sal_Int32 i = 0; i != k1; ++i) {
1024 b.append("[]");
1026 b.append(n);
1027 return b.makeStringAndClear();
1030 void CppuType::inc(sal_Int32 num)
1032 m_indentLength += num;
1035 void CppuType::dec(sal_Int32 num)
1037 m_indentLength = std::max< sal_Int32 >(m_indentLength - num, 0);
1040 OUString CppuType::indent() const
1042 OUStringBuffer buf(m_indentLength);
1043 for (sal_Int32 i = 0; i != m_indentLength; ++i) {
1044 buf.append(' ');
1046 return buf.makeStringAndClear();
1049 bool isDeprecated(std::vector< OUString > const & annotations)
1051 for (const OUString& r : annotations) {
1052 if (r == "deprecated") {
1053 return true;
1056 return false;
1059 void dumpDeprecation(FileStream & out, bool deprecated)
1061 if (deprecated) {
1062 out << "SAL_DEPRECATED_INTERNAL(\"marked @deprecated in UNOIDL\") ";
1066 class BaseOffset
1068 public:
1069 BaseOffset(
1070 rtl::Reference< TypeManager > manager,
1071 rtl::Reference< unoidl::InterfaceTypeEntity > const & entity):
1072 manager_(std::move(manager)), offset_(0) {
1073 calculateBases(entity);
1075 BaseOffset(const BaseOffset&) = delete;
1076 const BaseOffset& operator=(const BaseOffset&) = delete;
1078 sal_Int32 get() const {
1079 return offset_;
1082 private:
1083 void calculateBases(
1084 rtl::Reference< unoidl::InterfaceTypeEntity > const & entity);
1086 rtl::Reference< TypeManager > manager_;
1087 std::set< OUString > set_;
1088 sal_Int32 offset_;
1091 void BaseOffset::calculateBases(
1092 rtl::Reference< unoidl::InterfaceTypeEntity > const & entity)
1094 assert(entity.is());
1095 for (const unoidl::AnnotatedReference& ar : entity->getDirectMandatoryBases()) {
1096 if (set_.insert(ar.name).second) {
1097 rtl::Reference< unoidl::Entity > ent;
1098 codemaker::UnoType::Sort sort = manager_->getSort(ar.name, &ent);
1099 if (sort != codemaker::UnoType::Sort::Interface) {
1100 throw CannotDumpException(
1101 "interface type base " + ar.name
1102 + " is not an interface type");
1104 rtl::Reference< unoidl::InterfaceTypeEntity > ent2(
1105 dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get()));
1106 assert(ent2.is());
1107 calculateBases(ent2);
1108 offset_ += ent2->getDirectAttributes().size()
1109 + ent2->getDirectMethods().size(); //TODO: overflow
1114 class InterfaceType: public CppuType
1116 public:
1117 InterfaceType(
1118 rtl::Reference< unoidl::InterfaceTypeEntity > const & entity,
1119 OUString const & name, rtl::Reference< TypeManager > const & typeMgr);
1121 virtual void dumpDeclaration(FileStream& o) override;
1122 void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
1124 void dumpAttributes(FileStream& o) const;
1125 void dumpMethods(FileStream& o) const;
1126 void dumpNormalGetCppuType(FileStream& o) override;
1127 void dumpComprehensiveGetCppuType(FileStream& o) override;
1128 void dumpCppuAttributeRefs(FileStream& o, sal_uInt32& index);
1129 void dumpCppuMethodRefs(FileStream& o, sal_uInt32& index);
1130 void dumpCppuAttributes(FileStream& o, sal_uInt32& index);
1131 void dumpCppuMethods(FileStream& o, sal_uInt32& index);
1132 void dumpAttributesCppuDecl(FileStream & out, std::set< OUString > * seen) const;
1133 void dumpMethodsCppuDecl(FileStream & out, std::set< OUString > * seen) const;
1135 private:
1136 virtual void addComprehensiveGetCppuTypeIncludes(
1137 codemaker::cppumaker::Includes & includes) const override;
1139 virtual sal_uInt32 checkInheritedMemberCount() const override {
1140 return BaseOffset(m_typeMgr, entity_).get();
1143 void dumpExceptionTypeName(
1144 FileStream & out, std::u16string_view prefix, sal_uInt32 index,
1145 std::u16string_view name) const;
1147 sal_Int32 dumpExceptionTypeNames(
1148 FileStream & out, std::u16string_view prefix,
1149 std::vector< OUString > const & exceptions, bool runtimeException) const;
1151 rtl::Reference< unoidl::InterfaceTypeEntity > entity_;
1152 bool m_isDeprecated;
1155 InterfaceType::InterfaceType(
1156 rtl::Reference< unoidl::InterfaceTypeEntity > const & entity,
1157 OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
1158 CppuType(name, typeMgr), entity_(entity),
1159 m_isDeprecated(isDeprecated(entity->getAnnotations()))
1161 assert(entity.is());
1164 void InterfaceType::dumpDeclaration(FileStream & out)
1166 out << "\nclass SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI " << id_;
1167 for (std::vector< unoidl::AnnotatedReference >::const_iterator i(
1168 entity_->getDirectMandatoryBases().begin());
1169 i != entity_->getDirectMandatoryBases().end(); ++i) {
1170 out << (i == entity_->getDirectMandatoryBases().begin() ? " :" : ",")
1171 << " public " << codemaker::cpp::scopedCppName(u2b(i->name));
1173 out << "\n{\npublic:\n";
1174 inc();
1175 out << "#if defined LIBO_INTERNAL_ONLY\n"
1176 << indent() << id_ << "() = default;\n"
1177 << indent() << id_ << "(" << id_ << " const &) = default;\n"
1178 << indent() << id_ << "(" << id_ << " &&) = default;\n"
1179 << indent() << id_ << " & operator =(" << id_ << " const &) = default;\n"
1180 << indent() << id_ << " & operator =(" << id_ << " &&) = default;\n#endif\n\n";
1181 dumpAttributes(out);
1182 dumpMethods(out);
1183 out << "\n" << indent()
1184 << ("static inline ::css::uno::Type const & SAL_CALL"
1185 " static_type(void * = 0);\n\n");
1186 dec();
1187 out << "protected:\n";
1188 inc();
1189 out << indent() << "~" << id_
1190 << ("() SAL_NOEXCEPT {} // avoid warnings about virtual members and"
1191 " non-virtual dtor\n");
1192 dec();
1193 out << "};\n\n";
1196 void InterfaceType::dumpHppFile(
1197 FileStream & out, codemaker::cppumaker::Includes & includes)
1199 OUString headerDefine(dumpHeaderDefine(out, u"HPP"));
1200 out << "\n";
1201 addDefaultHxxIncludes(includes);
1202 includes.dump(out, &name_, !(m_cppuTypeLeak || m_cppuTypeDynamic));
1203 out << "\n#if defined LIBO_INTERNAL_ONLY\n#include <type_traits>\n#endif\n\n";
1204 dumpGetCppuType(out);
1205 out << "\n::css::uno::Type const & "
1206 << codemaker::cpp::scopedCppName(u2b(name_))
1207 << "::static_type(SAL_UNUSED_PARAMETER void *) {\n";
1208 inc();
1209 out << indent() << "return ::cppu::UnoType< ";
1210 dumpType(out, name_, false, false, true);
1211 out << " >::get();\n";
1212 dec();
1213 out << "}\n\n#if defined LIBO_INTERNAL_ONLY\nnamespace cppu::detail {\n";
1214 if (name_ == "com.sun.star.uno.XInterface") {
1215 out << "template<typename> struct IsUnoInterfaceType: ::std::false_type {};\n"
1216 "template<typename T> inline constexpr auto isUnoInterfaceType ="
1217 " sizeof (T) && IsUnoInterfaceType<T>::value;\n";
1219 out << "template<> struct IsUnoInterfaceType<";
1220 dumpType(out, name_, false, false, true);
1221 out << ">: ::std::true_type {};\n}\n#endif\n\n#endif // "<< headerDefine << "\n";
1224 void InterfaceType::dumpAttributes(FileStream & out) const
1226 if (!entity_->getDirectAttributes().empty()) {
1227 out << "\n" << indent() << "// Attributes\n";
1229 for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity_->getDirectAttributes()) {
1230 bool depr = m_isDeprecated || isDeprecated(attr.annotations);
1231 out << indent();
1232 dumpDeprecation(out, depr);
1233 out << "virtual ";
1234 dumpType(out, attr.type);
1235 out << " SAL_CALL get" << attr.name << "() = 0;\n";
1236 if (!attr.readOnly) {
1237 bool byRef = passByReference(attr.type);
1238 out << indent();
1239 dumpDeprecation(out, depr);
1240 out << "virtual void SAL_CALL set" << attr.name << "( ";
1241 dumpType(out, attr.type, byRef, byRef);
1242 out << " _" << attr.name.toAsciiLowerCase() << " ) = 0;\n";
1247 void InterfaceType::dumpMethods(FileStream & out) const
1249 if (!entity_->getDirectMethods().empty()) {
1250 out << "\n" << indent() << "// Methods\n";
1252 for (const unoidl::InterfaceTypeEntity::Method& method : entity_->getDirectMethods()) {
1253 out << indent();
1254 dumpDeprecation(out, m_isDeprecated || isDeprecated(method.annotations));
1255 out << "virtual ";
1256 dumpType(out, method.returnType);
1257 out << " SAL_CALL " << method.name << "(";
1258 if (!method.parameters.empty()) {
1259 out << " ";
1260 for (std::vector< unoidl::InterfaceTypeEntity::Method::Parameter >::
1261 const_iterator j(method.parameters.begin());
1262 j != method.parameters.end();) {
1263 bool isConst;
1264 bool isRef;
1265 if (j->direction
1266 == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN)
1268 isConst = passByReference(j->type);
1269 isRef = isConst;
1270 } else {
1271 isConst = false;
1272 isRef = true;
1274 dumpType(out, j->type, isConst, isRef);
1275 out << " " << j->name;
1276 ++j;
1277 if (j != method.parameters.end()) {
1278 out << ", ";
1281 out << " ";
1283 out << ") = 0;\n";
1287 void InterfaceType::dumpNormalGetCppuType(FileStream & out)
1289 dumpGetCppuTypePreamble(out);
1290 out << indent()
1291 << "static typelib_TypeDescriptionReference * the_type = 0;\n"
1292 << indent() << "if ( !the_type )\n" << indent() << "{\n";
1293 inc();
1294 std::vector< unoidl::AnnotatedReference >::size_type bases(
1295 entity_->getDirectMandatoryBases().size());
1296 if (bases == 1
1297 && (entity_->getDirectMandatoryBases()[0].name
1298 == "com.sun.star.uno.XInterface")) {
1299 bases = 0;
1301 if (bases != 0) {
1302 out << indent() << "typelib_TypeDescriptionReference * aSuperTypes["
1303 << entity_->getDirectMandatoryBases().size() << "];\n";
1304 std::vector< unoidl::AnnotatedReference >::size_type n = 0;
1305 for (const unoidl::AnnotatedReference& ar : entity_->getDirectMandatoryBases()) {
1306 out << indent() << "aSuperTypes[" << n++ << "] = ::cppu::UnoType< ";
1307 dumpType(out, ar.name, true, false, false, true);
1308 out << " >::get().getTypeLibType();\n";
1311 out << indent() << "typelib_static_mi_interface_type_init( &the_type, \""
1312 << name_ << "\", " << bases << ", "
1313 << (bases == 0 ? "0" : "aSuperTypes") << " );\n";
1314 dec();
1315 out << indent() << "}\n" << indent()
1316 << ("return * reinterpret_cast< ::css::uno::Type * >("
1317 " &the_type );\n");
1318 dumpGetCppuTypePostamble(out);
1321 void InterfaceType::dumpComprehensiveGetCppuType(FileStream & out)
1323 codemaker::cppumaker::dumpNamespaceOpen(out, name_, false);
1324 OUString staticTypeClass("the" + id_ + "Type");
1325 out << " namespace detail {\n\n" << indent() << "struct " << staticTypeClass
1326 << " : public rtl::StaticWithInit< ::css::uno::Type *, "
1327 << staticTypeClass << " >\n" << indent() << "{\n";
1328 inc();
1329 out << indent() << "::css::uno::Type * operator()() const\n"
1330 << indent() << "{\n";
1331 inc();
1332 out << indent() << "::rtl::OUString sTypeName( \"" << name_ << "\" );\n\n"
1333 << indent() << "// Start inline typedescription generation\n"
1334 << indent() << "typelib_InterfaceTypeDescription * pTD = 0;\n\n";
1335 out << indent() << "typelib_TypeDescriptionReference * aSuperTypes["
1336 << entity_->getDirectMandatoryBases().size() << "];\n";
1337 std::vector< unoidl::AnnotatedReference >::size_type n = 0;
1338 for (const unoidl::AnnotatedReference& ar : entity_->getDirectMandatoryBases()) {
1339 out << indent() << "aSuperTypes[" << n++ << "] = ::cppu::UnoType< ";
1340 dumpType(out, ar.name, false, false, false, true);
1341 out << " >::get().getTypeLibType();\n";
1343 std::size_t count = entity_->getDirectAttributes().size()
1344 + entity_->getDirectMethods().size(); //TODO: overflow
1345 if (count != 0) {
1346 out << indent() << "typelib_TypeDescriptionReference * pMembers["
1347 << count << "] = { ";
1348 for (std::size_t i = 0; i != count; ++i) {
1349 out << "0";
1350 if (i + 1 != count) {
1351 out << ",";
1354 out << " };\n";
1355 sal_uInt32 index = 0;
1356 dumpCppuAttributeRefs(out, index);
1357 dumpCppuMethodRefs(out, index);
1359 out << "\n" << indent() << "typelib_typedescription_newMIInterface(\n";
1360 inc();
1361 out << indent() << "&pTD,\n" << indent()
1362 << "sTypeName.pData, 0, 0, 0, 0, 0,\n" << indent()
1363 << entity_->getDirectMandatoryBases().size() << ", aSuperTypes,\n"
1364 << indent() << count << ",\n" << indent()
1365 << (count == 0 ? "0" : "pMembers") << " );\n\n";
1366 dec();
1367 out << indent()
1368 << ("typelib_typedescription_register( (typelib_TypeDescription**)&pTD"
1369 " );\n");
1370 for (std::size_t i = 0; i != count; ++i) {
1371 out << indent() << "typelib_typedescriptionreference_release( pMembers["
1372 << i << "] );\n";
1374 out << indent()
1375 << ("typelib_typedescription_release( (typelib_TypeDescription*)pTD"
1376 " );\n\n")
1377 << indent() << "return new ::css::uno::Type( "
1378 << getTypeClass(name_) << ", sTypeName ); // leaked\n";
1379 dec();
1380 out << indent() << "}\n";
1381 dec();
1382 out << indent() << "};\n\n";
1383 codemaker::cppumaker::dumpNamespaceClose(out, name_, false);
1384 out << " }\n\n";
1385 dumpGetCppuTypePreamble(out);
1386 out << indent() << "const ::css::uno::Type &rRet = *detail::"
1387 << staticTypeClass << "::get();\n" << indent()
1388 << "// End inline typedescription generation\n" << indent()
1389 << "static bool bInitStarted = false;\n" << indent()
1390 << "if (!bInitStarted)\n" << indent() << "{\n";
1391 inc();
1392 out << indent()
1393 << "::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );\n"
1394 << indent() << "if (!bInitStarted)\n" << indent() << "{\n";
1395 inc();
1396 out << indent() << "OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();\n"
1397 << indent() << "bInitStarted = true;\n";
1398 std::set< OUString > seen;
1399 // Type for RuntimeException is always needed:
1400 seen.insert(u"com.sun.star.uno.RuntimeException"_ustr);
1401 dumpCppuGetType(out, u"com.sun.star.uno.RuntimeException");
1402 dumpAttributesCppuDecl(out, &seen);
1403 dumpMethodsCppuDecl(out, &seen);
1404 if (count != 0) {
1405 sal_uInt32 index = getInheritedMemberCount();
1406 dumpCppuAttributes(out, index);
1407 dumpCppuMethods(out, index);
1409 dec();
1410 out << indent() << "}\n";
1411 dec();
1412 out << indent() << "}\n" << indent() << "else\n" << indent() << "{\n";
1413 inc();
1414 out << indent() << "OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();\n";
1415 dec();
1416 out << indent() << "}\n" << indent() << "return rRet;\n";
1417 dumpGetCppuTypePostamble(out);
1420 void InterfaceType::dumpCppuAttributeRefs(FileStream & out, sal_uInt32 & index)
1422 std::vector< unoidl::InterfaceTypeEntity::Attribute >::size_type n = 0;
1423 for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity_->getDirectAttributes()) {
1424 out << indent() << "::rtl::OUString sAttributeName" << n << "( \""
1425 << name_ << "::" << attr.name << "\" );\n" << indent()
1426 << "typelib_typedescriptionreference_new( &pMembers[" << index++
1427 << "],\n";
1428 inc(38);
1429 out << indent()
1430 << "(typelib_TypeClass)::css::uno::TypeClass_INTERFACE_ATTRIBUTE,\n"
1431 << indent() << "sAttributeName" << n << ".pData );\n";
1432 dec(38);
1433 ++n;
1437 void InterfaceType::dumpCppuMethodRefs(FileStream & out, sal_uInt32 & index)
1439 std::vector< unoidl::InterfaceTypeEntity::Method >::size_type n = 0;
1440 for (const unoidl::InterfaceTypeEntity::Method& method : entity_->getDirectMethods()) {
1441 out << indent() << "::rtl::OUString sMethodName" << n << "( \"" << name_
1442 << "::" << method.name << "\" );\n" << indent()
1443 << "typelib_typedescriptionreference_new( &pMembers[" << index++
1444 << "],\n";
1445 inc(38);
1446 out << indent()
1447 << "(typelib_TypeClass)::css::uno::TypeClass_INTERFACE_METHOD,\n"
1448 << indent() << "sMethodName" << n << ".pData );\n";
1449 dec(38);
1450 ++n;
1454 void InterfaceType::addComprehensiveGetCppuTypeIncludes(
1455 codemaker::cppumaker::Includes & includes) const
1457 // The comprehensive getCppuType method always includes a line
1458 // "getCppuType( (const ::css::uno::RuntimeException*)0 );":
1459 includes.addCppuUnotypeHxx();
1460 includes.addRtlInstanceHxx(); // using rtl::StaticWithInit
1461 includes.addOslMutexHxx();
1462 includes.add("com.sun.star.uno.RuntimeException"_ostr);
1465 void InterfaceType::dumpCppuAttributes(FileStream & out, sal_uInt32 & index)
1467 if (entity_->getDirectAttributes().empty())
1468 return;
1470 out << "\n" << indent()
1471 << "typelib_InterfaceAttributeTypeDescription * pAttribute = 0;\n";
1472 std::vector< unoidl::InterfaceTypeEntity::Attribute >::size_type n = 0;
1473 for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity_->getDirectAttributes()) {
1474 OUString type(resolveAllTypedefs(attr.type));
1475 out << indent() << "{\n";
1476 inc();
1477 out << indent() << "::rtl::OUString sAttributeType" << n << "( \""
1478 << type << "\" );\n" << indent()
1479 << "::rtl::OUString sAttributeName" << n << "( \"" << name_
1480 << "::" << attr.name << "\" );\n";
1481 sal_Int32 getExcn = dumpExceptionTypeNames(
1482 out, u"get", attr.getExceptions, false);
1483 sal_Int32 setExcn = dumpExceptionTypeNames(
1484 out, u"set", attr.setExceptions, false);
1485 out << indent()
1486 << ("typelib_typedescription_newExtendedInterfaceAttribute("
1487 " &pAttribute,\n");
1488 inc();
1489 out << indent() << index++ << ", sAttributeName" << n
1490 << ".pData,\n" << indent() << "(typelib_TypeClass)"
1491 << getTypeClass(type) << ", sAttributeType" << n << ".pData,\n"
1492 << indent() << "sal_" << (attr.readOnly ? "True" : "False")
1493 << ", " << getExcn << ", "
1494 << (getExcn == 0 ? "0" : "the_getExceptions") << ", " << setExcn
1495 << ", " << (setExcn == 0 ? "0" : "the_setExceptions")
1496 << " );\n";
1497 dec();
1498 out << indent()
1499 << ("typelib_typedescription_register("
1500 " (typelib_TypeDescription**)&pAttribute );\n");
1501 dec();
1502 out << indent() << "}\n";
1503 ++n;
1505 out << indent()
1506 << ("typelib_typedescription_release("
1507 " (typelib_TypeDescription*)pAttribute );\n");
1510 void InterfaceType::dumpCppuMethods(FileStream & out, sal_uInt32 & index)
1512 if (entity_->getDirectMethods().empty())
1513 return;
1515 out << "\n" << indent()
1516 << "typelib_InterfaceMethodTypeDescription * pMethod = 0;\n";
1517 std::vector< unoidl::InterfaceTypeEntity::Method >::size_type n = 0;
1518 for (const unoidl::InterfaceTypeEntity::Method& method : entity_->getDirectMethods()) {
1519 OUString returnType(resolveAllTypedefs(method.returnType));
1520 out << indent() << "{\n";
1521 inc();
1522 if (!method.parameters.empty()) {
1523 out << indent() << "typelib_Parameter_Init aParameters["
1524 << method.parameters.size() << "];\n";
1526 std::vector< unoidl::InterfaceTypeEntity::Method::Parameter >::
1527 size_type m = 0;
1528 for (const unoidl::InterfaceTypeEntity::Method::Parameter& param : method.parameters) {
1529 OUString type(resolveAllTypedefs(param.type));
1530 out << indent() << "::rtl::OUString sParamName" << m << "( \""
1531 << param.name << "\" );\n" << indent()
1532 << "::rtl::OUString sParamType" << m << "( \"" << type
1533 << "\" );\n" << indent() << "aParameters[" << m
1534 << "].pParamName = sParamName" << m << ".pData;\n"
1535 << indent() << "aParameters[" << m
1536 << "].eTypeClass = (typelib_TypeClass)"
1537 << getTypeClass(type) << ";\n" << indent() << "aParameters["
1538 << m << "].pTypeName = sParamType" << m << ".pData;\n"
1539 << indent() << "aParameters[" << m << "].bIn = "
1540 << ((param.direction
1541 == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT)
1542 ? "sal_False" : "sal_True")
1543 << ";\n" << indent() << "aParameters[" << m << "].bOut = "
1544 << ((param.direction
1545 == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN)
1546 ? "sal_False" : "sal_True")
1547 << ";\n";
1548 ++m;
1550 sal_Int32 excn = dumpExceptionTypeNames(
1551 out, u"", method.exceptions,
1552 method.name != "acquire" && method.name != "release");
1553 out << indent() << "::rtl::OUString sReturnType" << n << "( \""
1554 << returnType << "\" );\n" << indent()
1555 << "::rtl::OUString sMethodName" << n << "( \"" << name_ << "::"
1556 << method.name << "\" );\n" << indent()
1557 << "typelib_typedescription_newInterfaceMethod( &pMethod,\n";
1558 inc();
1559 out << indent() << index++ << ", sal_False,\n" << indent()
1560 << "sMethodName" << n << ".pData,\n" << indent()
1561 << "(typelib_TypeClass)" << getTypeClass(returnType)
1562 << ", sReturnType" << n << ".pData,\n" << indent()
1563 << method.parameters.size() << ", "
1564 << (method.parameters.empty() ? "0" : "aParameters") << ",\n"
1565 << indent() << excn << ", "
1566 << (excn == 0 ? "0" : "the_Exceptions") << " );\n";
1567 dec();
1568 out << indent()
1569 << ("typelib_typedescription_register("
1570 " (typelib_TypeDescription**)&pMethod );\n");
1571 dec();
1572 out << indent() << "}\n";
1573 ++n;
1575 out << indent()
1576 << ("typelib_typedescription_release("
1577 " (typelib_TypeDescription*)pMethod );\n");
1580 void InterfaceType::dumpAttributesCppuDecl(
1581 FileStream & out, std::set< OUString > * seen) const
1583 assert(seen != nullptr);
1584 for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity_->getDirectAttributes()) {
1585 if (seen->insert(attr.type).second) {
1586 dumpCppuGetType(out, attr.type);
1588 for (const OUString& exc : attr.getExceptions) {
1589 if (seen->insert(exc).second) {
1590 dumpCppuGetType(out, exc);
1593 for (const OUString& exc : attr.setExceptions) {
1594 if (seen->insert(exc).second) {
1595 dumpCppuGetType(out, exc);
1601 void InterfaceType::dumpMethodsCppuDecl(
1602 FileStream & out, std::set< OUString > * seen) const
1604 assert(seen != nullptr);
1605 for (const unoidl::InterfaceTypeEntity::Method& method : entity_->getDirectMethods()) {
1606 for (const OUString& ex : method.exceptions) {
1607 if (seen->insert(ex).second) {
1608 dumpCppuGetType(out, ex);
1614 void InterfaceType::dumpExceptionTypeName(
1615 FileStream & out, std::u16string_view prefix, sal_uInt32 index,
1616 std::u16string_view name) const
1618 out << indent() << "::rtl::OUString the_" << prefix << "ExceptionName"
1619 << index << "( \"" << name << "\" );\n";
1622 sal_Int32 InterfaceType::dumpExceptionTypeNames(
1623 FileStream & out, std::u16string_view prefix,
1624 std::vector< OUString > const & exceptions, bool runtimeException) const
1626 sal_Int32 count = 0;
1627 for (const OUString& ex : exceptions) {
1628 if (ex != "com.sun.star.uno.RuntimeException") {
1629 dumpExceptionTypeName(out, prefix, count++, ex);
1632 if (runtimeException) {
1633 dumpExceptionTypeName(
1634 out, prefix, count++, u"com.sun.star.uno.RuntimeException");
1636 if (count != 0) {
1637 out << indent() << "rtl_uString * the_" << prefix << "Exceptions[] = {";
1638 for (sal_Int32 i = 0; i != count; ++i) {
1639 out << (i == 0 ? " " : ", ") << "the_" << prefix << "ExceptionName"
1640 << i << ".pData";
1642 out << " };\n";
1644 return count;
1647 class ConstantGroup: public CppuType
1649 public:
1650 ConstantGroup(
1651 rtl::Reference< unoidl::ConstantGroupEntity > const & entity,
1652 OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
1653 CppuType(name, typeMgr), entity_(entity) {
1654 assert(entity.is());
1657 bool hasConstants() const {
1658 return !entity_->getMembers().empty();
1661 private:
1662 virtual void dumpHdlFile(
1663 FileStream & out, codemaker::cppumaker::Includes & includes) override;
1665 virtual void dumpHppFile(
1666 FileStream & out, codemaker::cppumaker::Includes & includes) override;
1668 virtual void dumpDeclaration(FileStream & out) override;
1670 rtl::Reference< unoidl::ConstantGroupEntity > entity_;
1673 void ConstantGroup::dumpHdlFile(
1674 FileStream & out, codemaker::cppumaker::Includes & includes)
1676 OUString headerDefine(dumpHeaderDefine(out, u"HDL"));
1677 out << "\n";
1678 addDefaultHIncludes(includes);
1679 includes.dump(out, nullptr, true);
1680 out << "\n";
1681 if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, true)) {
1682 out << "\n";
1684 out << "\n";
1685 dumpDeclaration(out);
1686 out << "\n";
1687 if (codemaker::cppumaker::dumpNamespaceClose(out, name_, true)) {
1688 out << "\n";
1690 out << "\n#endif // "<< headerDefine << "\n";
1693 void ConstantGroup::dumpHppFile(
1694 FileStream & out, codemaker::cppumaker::Includes &)
1696 OUString headerDefine(dumpHeaderDefine(out, u"HPP"));
1697 out << "\n";
1698 codemaker::cppumaker::Includes::dumpInclude(out, u2b(name_), false);
1699 out << "\n#endif // "<< headerDefine << "\n";
1702 void ConstantGroup::dumpDeclaration(FileStream & out)
1704 for (const unoidl::ConstantGroupEntity::Member& member : entity_->getMembers()) {
1705 out << "static const ";
1706 switch (member.value.type) {
1707 case unoidl::ConstantValue::TYPE_BOOLEAN:
1708 out << "::sal_Bool";
1709 break;
1710 case unoidl::ConstantValue::TYPE_BYTE:
1711 out << "::sal_Int8";
1712 break;
1713 case unoidl::ConstantValue::TYPE_SHORT:
1714 out << "::sal_Int16";
1715 break;
1716 case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
1717 out << "::sal_uInt16";
1718 break;
1719 case unoidl::ConstantValue::TYPE_LONG:
1720 out << "::sal_Int32";
1721 break;
1722 case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
1723 out << "::sal_uInt32";
1724 break;
1725 case unoidl::ConstantValue::TYPE_HYPER:
1726 out << "::sal_Int64";
1727 break;
1728 case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
1729 out << "::sal_uInt64";
1730 break;
1731 case unoidl::ConstantValue::TYPE_FLOAT:
1732 out << "float";
1733 break;
1734 case unoidl::ConstantValue::TYPE_DOUBLE:
1735 out << "double";
1736 break;
1738 out << " "
1739 << codemaker::cpp::translateUnoToCppIdentifier(
1740 u2b(member.name), "constant",
1741 codemaker::cpp::IdentifierTranslationMode::KeywordsOnly)
1742 << " = ";
1743 switch (member.value.type) {
1744 case unoidl::ConstantValue::TYPE_BOOLEAN:
1745 out << (member.value.booleanValue ? "sal_True" : "sal_False");
1746 break;
1747 case unoidl::ConstantValue::TYPE_BYTE:
1748 out << "(sal_Int8)" << OUString::number(member.value.byteValue);
1749 break;
1750 case unoidl::ConstantValue::TYPE_SHORT:
1751 out << "(sal_Int16)" << OUString::number(member.value.shortValue);
1752 break;
1753 case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
1754 out << "(sal_uInt16)"
1755 << OUString::number(member.value.unsignedShortValue);
1756 break;
1757 case unoidl::ConstantValue::TYPE_LONG:
1758 // Avoid C++ compiler warnings about (un)signedness of literal
1759 // -2^31:
1760 if (member.value.longValue == SAL_MIN_INT32) {
1761 out << "SAL_MIN_INT32";
1762 } else {
1763 out << "(sal_Int32)" << OUString::number(member.value.longValue);
1765 break;
1766 case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
1767 out << "(sal_uInt32)"
1768 << OUString::number(member.value.unsignedLongValue) << "U";
1769 break;
1770 case unoidl::ConstantValue::TYPE_HYPER:
1771 // Avoid C++ compiler warnings about (un)signedness of literal
1772 // -2^63:
1773 if (member.value.hyperValue == SAL_MIN_INT64) {
1774 out << "SAL_MIN_INT64";
1775 } else {
1776 out << "(sal_Int64) SAL_CONST_INT64("
1777 << OUString::number(member.value.hyperValue) << ")";
1779 break;
1780 case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
1781 out << "SAL_CONST_UINT64("
1782 << OUString::number(member.value.unsignedHyperValue) << ")";
1783 break;
1784 case unoidl::ConstantValue::TYPE_FLOAT:
1785 out << "(float)" << OUString::number(member.value.floatValue);
1786 break;
1787 case unoidl::ConstantValue::TYPE_DOUBLE:
1788 out << "(double)" << OUString::number(member.value.doubleValue);
1789 break;
1791 out << ";\n";
1795 void dumpTypeParameterName(FileStream & out, std::u16string_view name)
1797 // Prefix all type parameters with "typeparam_" to avoid problems when a
1798 // struct member has the same name as a type parameter, as in
1799 // struct<T> { T T; };
1800 out << "typeparam_" << name;
1803 class PlainStructType: public CppuType
1805 public:
1806 PlainStructType(
1807 rtl::Reference< unoidl::PlainStructTypeEntity > const & entity,
1808 OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
1809 CppuType(name, typeMgr), entity_(entity) {
1810 assert(entity.is());
1813 private:
1814 virtual sal_uInt32 checkInheritedMemberCount() const override {
1815 return getTotalMemberCount(entity_->getDirectBase());
1818 virtual void dumpDeclaration(FileStream& o) override;
1820 void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
1822 virtual void dumpLightGetCppuType(FileStream & out) override;
1824 virtual void dumpNormalGetCppuType(FileStream & out) override;
1826 virtual void dumpComprehensiveGetCppuType(FileStream & out) override;
1828 virtual void addLightGetCppuTypeIncludes(
1829 codemaker::cppumaker::Includes & includes) const override;
1831 virtual void addNormalGetCppuTypeIncludes(
1832 codemaker::cppumaker::Includes & includes) const override;
1834 virtual void addComprehensiveGetCppuTypeIncludes(
1835 codemaker::cppumaker::Includes & includes) const override;
1837 bool dumpBaseMembers(
1838 FileStream & out, OUString const & base, bool withType);
1840 sal_uInt32 getTotalMemberCount(OUString const & base) const;
1842 rtl::Reference< unoidl::PlainStructTypeEntity > entity_;
1845 void PlainStructType::dumpDeclaration(FileStream & out)
1847 out << "\n#ifdef _WIN32\n# pragma pack(push, 8)\n#endif\n\n" << indent();
1848 out << "struct SAL_DLLPUBLIC_RTTI ";
1849 if (canBeWarnUnused(name_))
1850 out << "SAL_WARN_UNUSED ";
1851 out << id_;
1852 OUString base(entity_->getDirectBase());
1853 if (!base.isEmpty()) {
1854 out << ": public " << codemaker::cpp::scopedCppName(u2b(base));
1856 out << " {\n";
1857 inc();
1858 out << indent() << "inline " << id_ << "();\n";
1859 if (!entity_->getDirectMembers().empty() || getInheritedMemberCount() > 0) {
1860 out << "\n" << indent() << "inline " << id_ << "(";
1861 bool bFirst = !dumpBaseMembers(out, base, true);
1862 for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) {
1863 if (!bFirst) {
1864 out << ", ";
1866 dumpType(out, member.type, true, true);
1867 out << " " << member.name << "_";
1868 bFirst = false;
1870 out << ");\n";
1872 if (!entity_->getDirectMembers().empty()) {
1873 out << "\n";
1874 for (std::vector< unoidl::PlainStructTypeEntity::Member >::
1875 const_iterator i(entity_->getDirectMembers().begin());
1876 i != entity_->getDirectMembers().end(); ++i) {
1877 out << indent();
1878 dumpType(out, i->type);
1879 out << " " << i->name;
1880 if (i == entity_->getDirectMembers().begin() && !base.isEmpty()
1881 && i->type != "hyper" && i->type != "unsigned hyper"
1882 && i->type != "double") {
1883 out << " CPPU_GCC3_ALIGN("
1884 << codemaker::cpp::scopedCppName(u2b(base)) << ")";
1886 out << ";\n";
1889 dec();
1890 out << "};\n\n#ifdef _WIN32\n# pragma pack(pop)\n#endif\n\n";
1893 void PlainStructType::dumpHppFile(
1894 FileStream & out, codemaker::cppumaker::Includes & includes)
1896 OUString headerDefine(dumpHeaderDefine(out, u"HPP"));
1897 out << "\n";
1898 includes.dump(out, &name_, true);
1899 out << "\n";
1900 if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) {
1901 out << "\n";
1903 out << "\ninline " << id_ << "::" << id_ << "()\n";
1904 inc();
1905 OUString base(entity_->getDirectBase());
1906 bool bFirst = true;
1907 if (!base.isEmpty()) {
1908 out << indent() << ": " << codemaker::cpp::scopedCppName(u2b(base))
1909 << "()\n";
1910 bFirst = false;
1912 for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) {
1913 out << indent() << (bFirst ? ":" : ",") << " " << member.name;
1914 dumpInitializer(out, false, member.type);
1915 out << "\n";
1916 bFirst = false;
1918 dec();
1919 out << "{\n}\n\n";
1920 if (!entity_->getDirectMembers().empty() || getInheritedMemberCount() > 0) {
1921 out << "inline " << id_;
1922 out << "::" << id_ << "(";
1923 bFirst = !dumpBaseMembers(out, base, true);
1924 for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) {
1925 if (!bFirst) {
1926 out << ", ";
1928 dumpType(out, member.type, true, true);
1929 out << " " << member.name << "_";
1930 bFirst = false;
1932 out << ")\n";
1933 inc();
1934 bFirst = true;
1935 if (!base.isEmpty()) {
1936 out << indent() << ": " << codemaker::cpp::scopedCppName(u2b(base))
1937 << "(";
1938 dumpBaseMembers(out, base, false);
1939 out << ")\n";
1940 bFirst = false;
1942 for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) {
1943 out << indent() << (bFirst ? ":" : ",") << " " << member.name << "("
1944 << member.name << "_)\n";
1945 bFirst = false;
1947 dec();
1948 out << "{\n}\n\n";
1950 // print the operator==
1951 out << "\ninline bool operator==(const " << id_ << "& the_lhs, const " << id_ << "& the_rhs)\n";
1952 out << "{\n";
1953 inc();
1954 out << indent() << "return ";
1955 bFirst = true;
1956 if (!base.isEmpty()) {
1957 out << "operator==( static_cast< " << codemaker::cpp::scopedCppName(u2b(base))
1958 << ">(the_lhs), static_cast< " << codemaker::cpp::scopedCppName(u2b(base)) << ">(the_rhs) )\n";
1959 bFirst = false;
1961 for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) {
1962 if (!bFirst)
1963 out << "\n" << indent() << indent() << "&& ";
1964 out << "the_lhs." << member.name << " == the_rhs." << member.name;
1965 bFirst = false;
1967 out << ";\n";
1968 dec();
1969 out << "}\n";
1970 // print the operator!=
1971 out << "\ninline bool operator!=(const " << id_ << "& the_lhs, const " << id_ << "& the_rhs)\n";
1972 out << "{\n";
1973 out << indent() << "return !operator==(the_lhs, the_rhs);\n";
1974 out << "}\n";
1975 // close namespace
1976 if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) {
1977 out << "\n";
1979 out << "\n";
1980 dumpGetCppuType(out);
1981 out << "\n#endif // "<< headerDefine << "\n";
1984 void PlainStructType::dumpLightGetCppuType(FileStream & out)
1986 dumpGetCppuTypePreamble(out);
1987 out << indent()
1988 << ("//TODO: On certain platforms with weak memory models, the"
1989 " following code can result in some threads observing that the_type"
1990 " points to garbage\n")
1991 << indent()
1992 << "static ::typelib_TypeDescriptionReference * the_type = 0;\n"
1993 << indent() << "if (the_type == 0) {\n";
1994 inc();
1995 out << indent() << "::typelib_static_type_init(&the_type, "
1996 << getTypeClass(name_, true) << ", \"" << name_ << "\");\n";
1997 dec();
1998 out << indent() << "}\n" << indent()
1999 << "return *reinterpret_cast< ::css::uno::Type * >(&the_type);\n";
2000 dumpGetCppuTypePostamble(out);
2003 void PlainStructType::dumpNormalGetCppuType(FileStream & out)
2005 dumpGetCppuTypePreamble(out);
2006 out << indent()
2007 << ("//TODO: On certain platforms with weak memory models, the"
2008 " following code can result in some threads observing that the_type"
2009 " points to garbage\n")
2010 << indent()
2011 << "static ::typelib_TypeDescriptionReference * the_type = 0;\n"
2012 << indent() << "if (the_type == 0) {\n";
2013 inc();
2014 out << indent()
2015 << "::typelib_TypeDescriptionReference * the_members[] = {\n";
2016 inc();
2017 for (std::vector< unoidl::PlainStructTypeEntity::Member >::const_iterator i(
2018 entity_->getDirectMembers().begin());
2019 i != entity_->getDirectMembers().end();) {
2020 out << indent() << "::cppu::UnoType< ";
2021 dumpType(out, i->type, false, false, false, true);
2022 ++i;
2023 out << " >::get().getTypeLibType()"
2024 << (i == entity_->getDirectMembers().end() ? " };" : ",") << "\n";
2026 dec();
2027 out << indent() << "::typelib_static_struct_type_init(&the_type, \""
2028 << name_ << "\", ";
2029 if (entity_->getDirectBase().isEmpty()) {
2030 out << "0";
2031 } else {
2032 out << "::cppu::UnoType< ";
2033 dumpType(out, entity_->getDirectBase(), false, false, false, true);
2034 out << " >::get().getTypeLibType()";
2036 out << ", " << entity_->getDirectMembers().size() << ", the_members, 0);\n";
2037 dec();
2038 out << indent() << "}\n" << indent()
2039 << "return *reinterpret_cast< ::css::uno::Type * >(&the_type);\n";
2040 dumpGetCppuTypePostamble(out);
2043 void PlainStructType::dumpComprehensiveGetCppuType(FileStream & out)
2045 OUString staticTypeClass("the" + id_ + "Type");
2046 codemaker::cppumaker::dumpNamespaceOpen(out, name_, false);
2047 out << " namespace detail {\n\n" << indent() << "struct "
2048 << staticTypeClass
2049 << " : public rtl::StaticWithInit< ::css::uno::Type *, "
2050 << staticTypeClass << " >\n" << indent() << "{\n";
2051 inc();
2052 out << indent() << "::css::uno::Type * operator()() const\n"
2053 << indent() << "{\n";
2054 inc();
2055 out << indent() << "::rtl::OUString the_name( \"" << name_ << "\" );\n";
2056 std::map< OUString, sal_uInt32 > types;
2057 std::vector< unoidl::PlainStructTypeEntity::Member >::size_type n = 0;
2058 for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) {
2059 if (types.emplace(
2060 member.type, static_cast< sal_uInt32 >(types.size())).
2061 second) {
2062 dumpCppuGetType(out, member.type, &name_);
2063 // For typedefs, use the resolved type name, as there will be no
2064 // information available about the typedef itself at runtime (the
2065 // above getCppuType call will make available information about the
2066 // resolved type); no extra #include for the resolved type is
2067 // needed, as the header for the typedef includes it already:
2068 out << indent() << "::rtl::OUString the_tname"
2069 << static_cast< sal_uInt32 >(types.size() - 1) << "( \""
2070 << resolveAllTypedefs(member.type) << "\" );\n";
2072 out << indent() << "::rtl::OUString the_name" << n++ << "( \""
2073 << member.name << "\" );\n";
2075 out << indent() << "::typelib_StructMember_Init the_members[] = {\n";
2076 inc();
2077 n = 0;
2078 for (std::vector< unoidl::PlainStructTypeEntity::Member >::const_iterator i(
2079 entity_->getDirectMembers().begin());
2080 i != entity_->getDirectMembers().end();) {
2081 const auto iter = types.find(i->type);
2082 assert(iter != types.end());
2083 out << indent() << "{ { " << getTypeClass(i->type, true)
2084 << ", the_tname" << iter->second
2085 << ".pData, the_name" << n++ << ".pData }, false }";
2086 ++i;
2087 out << (i == entity_->getDirectMembers().end() ? " };" : ",") << "\n";
2089 dec();
2090 out << indent() << "::typelib_TypeDescription * the_newType = 0;\n"
2091 << indent()
2092 << "::typelib_typedescription_newStruct(&the_newType, the_name.pData, ";
2093 if (entity_->getDirectBase().isEmpty()) {
2094 out << "0";
2095 } else {
2096 out << "::cppu::UnoType< ";
2097 dumpType(out, entity_->getDirectBase(), false, false, false, true);
2098 out << " >::get().getTypeLibType()";
2100 out << ", " << entity_->getDirectMembers().size() << ", the_members);\n"
2101 << indent() << "::typelib_typedescription_register(&the_newType);\n"
2102 << indent() << "::typelib_typedescription_release(the_newType);\n"
2103 << indent() << "return new ::css::uno::Type("
2104 << getTypeClass(name_) << ", the_name); // leaked\n";
2105 dec();
2106 out << indent() << "}\n";
2107 dec();
2108 out << indent() << "};\n";
2109 codemaker::cppumaker::dumpNamespaceClose(out, name_, false);
2110 out << " }\n\n";
2111 dumpGetCppuTypePreamble(out);
2112 out << indent() << "return *detail::" << staticTypeClass << "::get();\n";
2113 dumpGetCppuTypePostamble(out);
2116 bool PlainStructType::dumpBaseMembers(
2117 FileStream & out, OUString const & base, bool withType)
2119 if (base.isEmpty())
2120 return false;
2122 rtl::Reference< unoidl::Entity > ent;
2123 codemaker::UnoType::Sort sort = m_typeMgr->getSort(base, &ent);
2124 if (sort != codemaker::UnoType::Sort::PlainStruct) {
2125 throw CannotDumpException(
2126 "plain struct type base " + base
2127 + " is not a plain struct type");
2129 rtl::Reference< unoidl::PlainStructTypeEntity > ent2(
2130 dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get()));
2131 assert(ent2.is());
2132 if (!ent2.is()) {
2133 return false;
2135 bool hasMember = dumpBaseMembers(out, ent2->getDirectBase(), withType);
2136 for (const unoidl::PlainStructTypeEntity::Member& member : ent2->getDirectMembers()) {
2137 if (hasMember) {
2138 out << ", ";
2140 if (withType) {
2141 dumpType(out, member.type, true, true);
2142 out << " ";
2144 out << member.name << "_";
2145 hasMember = true;
2147 return hasMember;
2150 void PlainStructType::addLightGetCppuTypeIncludes(
2151 codemaker::cppumaker::Includes & includes) const
2153 includes.addType();
2154 includes.addCppuUnotypeHxx();
2155 includes.addSalTypesH();
2156 includes.addTypelibTypeclassH();
2157 includes.addTypelibTypedescriptionH();
2160 void PlainStructType::addNormalGetCppuTypeIncludes(
2161 codemaker::cppumaker::Includes & includes) const
2163 includes.addType();
2164 includes.addCppuUnotypeHxx();
2165 includes.addSalTypesH();
2166 includes.addTypelibTypeclassH();
2167 includes.addTypelibTypedescriptionH();
2170 void PlainStructType::addComprehensiveGetCppuTypeIncludes(
2171 codemaker::cppumaker::Includes & includes) const
2173 includes.addType();
2174 includes.addCppuUnotypeHxx();
2175 includes.addRtlInstanceHxx();
2176 includes.addRtlUstringH();
2177 includes.addRtlUstringHxx();
2178 includes.addSalTypesH();
2179 includes.addTypelibTypeclassH();
2180 includes.addTypelibTypedescriptionH();
2183 sal_uInt32 PlainStructType::getTotalMemberCount(OUString const & base) const
2185 if (base.isEmpty()) {
2186 return 0;
2188 rtl::Reference< unoidl::Entity > ent;
2189 codemaker::UnoType::Sort sort = m_typeMgr->getSort(base, &ent);
2190 if (sort != codemaker::UnoType::Sort::PlainStruct) {
2191 throw CannotDumpException(
2192 "plain struct type base " + base + " is not a plain struct type");
2194 rtl::Reference< unoidl::PlainStructTypeEntity > ent2(
2195 dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get()));
2196 assert(ent2.is());
2197 if (!ent2.is()) {
2198 return 0;
2200 return getTotalMemberCount(ent2->getDirectBase())
2201 + ent2->getDirectMembers().size(); //TODO: overflow
2204 class PolyStructType: public CppuType
2206 public:
2207 PolyStructType(
2208 rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > const &
2209 entity,
2210 OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
2211 CppuType(name, typeMgr), entity_(entity) {
2212 assert(entity.is());
2215 private:
2216 virtual void dumpDeclaration(FileStream& o) override;
2218 void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
2220 virtual void dumpLightGetCppuType(FileStream & out) override;
2222 virtual void dumpNormalGetCppuType(FileStream & out) override;
2224 virtual void dumpComprehensiveGetCppuType(FileStream & out) override;
2226 virtual void addLightGetCppuTypeIncludes(
2227 codemaker::cppumaker::Includes & includes) const override;
2229 virtual void addNormalGetCppuTypeIncludes(
2230 codemaker::cppumaker::Includes & includes) const override;
2232 virtual void addComprehensiveGetCppuTypeIncludes(
2233 codemaker::cppumaker::Includes & includes) const override;
2235 virtual bool isPolymorphic() const override {
2236 return true;
2239 virtual void dumpTemplateHead(FileStream & out) const override;
2241 virtual void dumpTemplateParameters(FileStream & out) const override;
2243 rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > entity_;
2246 void PolyStructType::dumpDeclaration(FileStream & out)
2248 out << "\n#ifdef _WIN32\n# pragma pack(push, 8)\n#endif\n\n" << indent();
2249 dumpTemplateHead(out);
2250 out << "struct SAL_DLLPUBLIC_RTTI " << id_ << " {\n";
2251 inc();
2252 out << indent() << "inline " << id_ << "();\n";
2253 if (!entity_->getMembers().empty()) {
2254 out << "\n" << indent() << "inline " << id_ << "(";
2255 for (std::vector<
2256 unoidl::PolymorphicStructTypeTemplateEntity::Member >::
2257 const_iterator i(entity_->getMembers().begin());
2258 i != entity_->getMembers().end(); ++i) {
2259 if (i != entity_->getMembers().begin()) {
2260 out << ", ";
2262 if (i->parameterized) {
2263 dumpTypeParameterName(out, i->type);
2264 out << " const &";
2265 } else {
2266 dumpType(out, i->type, true, true);
2268 out << " " << i->name << "_";
2270 out << ");\n\n";
2271 // print the member fields
2272 for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member :
2273 entity_->getMembers()) {
2274 out << indent();
2275 if (member.parameterized) {
2276 dumpTypeParameterName(out, member.type);
2277 } else {
2278 dumpType(out, member.type);
2280 out << " " << member.name << ";\n";
2283 dec();
2284 out << "};\n\n#ifdef _WIN32\n# pragma pack(pop)\n#endif\n\n";
2287 void PolyStructType::dumpHppFile(
2288 FileStream & out, codemaker::cppumaker::Includes & includes)
2290 OUString headerDefine(dumpHeaderDefine(out, u"HPP"));
2291 out << "\n";
2292 includes.dump(out, &name_, true);
2293 out << "\n";
2294 if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) {
2295 out << "\n";
2297 out << "\n";
2298 // dump default (no-arg) constructor
2299 dumpTemplateHead(out);
2300 out << "inline " << id_;
2301 dumpTemplateParameters(out);
2302 out << "::" << id_ << "()\n";
2303 inc();
2304 for (std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >::
2305 const_iterator i(entity_->getMembers().begin());
2306 i != entity_->getMembers().end(); ++i) {
2307 out << indent() << (i == entity_->getMembers().begin() ? ":" : ",")
2308 << " " << i->name;
2309 dumpInitializer(out, i->parameterized, i->type);
2310 out << "\n";
2312 dec();
2313 out << "{\n}\n\n";
2314 if (!entity_->getMembers().empty()) {
2315 // dump takes-all-fields constructor
2316 dumpTemplateHead(out);
2317 out << "inline " << id_;
2318 dumpTemplateParameters(out);
2319 out << "::" << id_ << "(";
2320 for (std::vector<
2321 unoidl::PolymorphicStructTypeTemplateEntity::Member >::
2322 const_iterator i(entity_->getMembers().begin());
2323 i != entity_->getMembers().end(); ++i) {
2324 if (i != entity_->getMembers().begin()) {
2325 out << ", ";
2327 if (i->parameterized) {
2328 dumpTypeParameterName(out, i->type);
2329 out << " const &";
2330 } else {
2331 dumpType(out, i->type, true, true);
2333 out << " " << i->name << "_";
2335 out << ")\n";
2336 inc();
2337 for (std::vector<
2338 unoidl::PolymorphicStructTypeTemplateEntity::Member >::
2339 const_iterator i(entity_->getMembers().begin());
2340 i != entity_->getMembers().end(); ++i) {
2341 out << indent() << (i == entity_->getMembers().begin() ? ":" : ",")
2342 << " " << i->name << "(" << i->name << "_)\n";
2344 dec();
2345 out << "{\n}\n\n" << indent();
2346 // dump make_T method
2347 dumpTemplateHead(out);
2348 out << "\n" << indent() << "inline " << id_;
2349 dumpTemplateParameters(out);
2350 out << "\n" << indent() << "make_" << id_ << "(";
2351 for (std::vector<
2352 unoidl::PolymorphicStructTypeTemplateEntity::Member >::
2353 const_iterator i(entity_->getMembers().begin());
2354 i != entity_->getMembers().end(); ++i) {
2355 if (i != entity_->getMembers().begin()) {
2356 out << ", ";
2358 if (i->parameterized) {
2359 dumpTypeParameterName(out, i->type);
2360 out << " const &";
2361 } else {
2362 dumpType(out, i->type, true, true);
2364 out << " " << i->name << "_";
2366 out << ")\n" << indent() << "{\n";
2367 inc();
2368 out << indent() << "return " << id_;
2369 dumpTemplateParameters(out);
2370 out << "(";
2371 for (std::vector<
2372 unoidl::PolymorphicStructTypeTemplateEntity::Member >::
2373 const_iterator i(entity_->getMembers().begin());
2374 i != entity_->getMembers().end(); ++i) {
2375 if (i != entity_->getMembers().begin()) {
2376 out << ", ";
2378 out << i->name << "_";
2380 out << ");\n";
2381 dec();
2382 out << indent() << "}\n\n";
2384 // print the operator==
2385 dumpTemplateHead(out);
2386 out << " inline bool operator==(const " << id_;
2387 dumpTemplateParameters(out);
2388 out << "& the_lhs, const " << id_;
2389 dumpTemplateParameters(out);
2390 out << "& the_rhs)\n";
2391 out << "{\n";
2392 inc();
2393 out << indent() << "return ";
2394 bool bFirst = true;
2395 for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity_->getMembers()) {
2396 if (!bFirst)
2397 out << "\n" << indent() << indent() << "&& ";
2398 out << "the_lhs." << member.name << " == the_rhs." << member.name;
2399 bFirst = false;
2401 out << ";\n";
2402 dec();
2403 out << "}\n";
2404 // print the operator!=
2405 dumpTemplateHead(out);
2406 out << " inline bool operator!=(const " << id_;
2407 dumpTemplateParameters(out);
2408 out << "& the_lhs, const " << id_;
2409 dumpTemplateParameters(out);
2410 out << "& the_rhs)\n";
2411 out << "{\n";
2412 out << indent() << "return !operator==(the_lhs, the_rhs);\n";
2413 out << "}\n";
2414 // close namespace
2415 if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) {
2416 out << "\n";
2418 out << "\n";
2419 dumpGetCppuType(out);
2420 out << "\n#endif // "<< headerDefine << "\n";
2423 void PolyStructType::dumpLightGetCppuType(FileStream & out)
2425 dumpGetCppuTypePreamble(out);
2426 out << indent()
2427 << ("//TODO: On certain platforms with weak memory models, the"
2428 " following code can result in some threads observing that the_type"
2429 " points to garbage\n")
2430 << indent()
2431 << "static ::typelib_TypeDescriptionReference * the_type = 0;\n"
2432 << indent() << "if (the_type == 0) {\n";
2433 inc();
2435 out << "#ifdef LIBO_INTERNAL_ONLY\n";
2437 out << indent() << "::rtl::OString the_buffer = \"" << name_
2438 << "<\" +\n";
2439 for (std::vector< OUString >::const_iterator i(
2440 entity_->getTypeParameters().begin());
2441 i != entity_->getTypeParameters().end();) {
2442 out << indent()
2443 << ("::rtl::OUStringToOString("
2444 "::cppu::getTypeFavourChar(static_cast< ");
2445 dumpTypeParameterName(out, *i);
2446 out << " * >(0)).getTypeName(), RTL_TEXTENCODING_UTF8) +\n";
2447 ++i;
2448 if (i != entity_->getTypeParameters().end()) {
2449 out << indent() << "\",\" +\n";
2452 out << indent() << "\">\";\n";
2454 out << "#else\n";
2456 out << indent() << "::rtl::OStringBuffer the_buffer(\"" << name_
2457 << "<\");\n";
2458 for (std::vector< OUString >::const_iterator i(
2459 entity_->getTypeParameters().begin());
2460 i != entity_->getTypeParameters().end();) {
2461 out << indent()
2462 << ("the_buffer.append(::rtl::OUStringToOString("
2463 "::cppu::getTypeFavourChar(static_cast< ");
2464 dumpTypeParameterName(out, *i);
2465 out << " * >(0)).getTypeName(), RTL_TEXTENCODING_UTF8));\n";
2466 ++i;
2467 if (i != entity_->getTypeParameters().end()) {
2468 out << indent() << "the_buffer.append(',');\n";
2471 out << indent() << "the_buffer.append('>');\n";
2473 out << "#endif\n";
2475 out << indent()
2476 << "::typelib_static_type_init(&the_type, " << getTypeClass(name_, true)
2477 << ", the_buffer.getStr());\n";
2479 dec();
2480 out << indent() << "}\n" << indent()
2481 << "return *reinterpret_cast< ::css::uno::Type * >(&the_type);\n";
2482 dumpGetCppuTypePostamble(out);
2485 void PolyStructType::dumpNormalGetCppuType(FileStream & out)
2487 dumpGetCppuTypePreamble(out);
2488 out << indent()
2489 << ("//TODO: On certain platforms with weak memory models, the"
2490 " following code can result in some threads observing that the_type"
2491 " points to garbage\n")
2492 << indent()
2493 << "static ::typelib_TypeDescriptionReference * the_type = 0;\n"
2494 << indent() << "if (the_type == 0) {\n";
2495 inc();
2496 out << indent() << "::rtl::OStringBuffer the_buffer(\"" << name_
2497 << "<\");\n";
2498 for (std::vector< OUString >::const_iterator i(
2499 entity_->getTypeParameters().begin());
2500 i != entity_->getTypeParameters().end();) {
2501 out << indent()
2502 << ("the_buffer.append(::rtl::OUStringToOString("
2503 "::cppu::getTypeFavourChar(static_cast< ");
2504 dumpTypeParameterName(out, *i);
2505 out << " * >(0)).getTypeName(), RTL_TEXTENCODING_UTF8));\n";
2506 ++i;
2507 if (i != entity_->getTypeParameters().end()) {
2508 out << indent() << "the_buffer.append(',');\n";
2511 out << indent() << "the_buffer.append('>');\n" << indent()
2512 << "::typelib_TypeDescriptionReference * the_members[] = {\n";
2513 inc();
2514 for (std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >::
2515 const_iterator i(entity_->getMembers().begin());
2516 i != entity_->getMembers().end();) {
2517 out << indent();
2518 if (i->parameterized) {
2519 out << "::cppu::getTypeFavourChar(static_cast< ";
2520 dumpTypeParameterName(out, i->type);
2521 out << " * >(0))";
2522 } else {
2523 out << "::cppu::UnoType< ";
2524 dumpType(out, i->type, false, false, false, true);
2525 out << " >::get()";
2527 ++i;
2528 out << ".getTypeLibType()"
2529 << (i == entity_->getMembers().end() ? " };" : ",") << "\n";
2531 dec();
2532 out << indent() << "static ::sal_Bool const the_parameterizedTypes[] = { ";
2533 for (std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >::
2534 const_iterator i(entity_->getMembers().begin());
2535 i != entity_->getMembers().end(); ++i) {
2536 if (i != entity_->getMembers().begin()) {
2537 out << ", ";
2539 out << (i->parameterized ? "true" : "false");
2541 out << " };\n" << indent()
2542 << ("::typelib_static_struct_type_init(&the_type, the_buffer.getStr(),"
2543 " 0, ")
2544 << entity_->getMembers().size()
2545 << ", the_members, the_parameterizedTypes);\n";
2546 dec();
2547 out << indent() << "}\n" << indent()
2548 << ("return *reinterpret_cast< ::css::uno::Type * >("
2549 "&the_type);\n");
2550 dumpGetCppuTypePostamble(out);
2553 void PolyStructType::dumpComprehensiveGetCppuType(FileStream & out)
2555 out << "namespace cppu { namespace detail {\n\n" << indent();
2556 dumpTemplateHead(out);
2557 OUString staticTypeClass("the" + id_ + "Type");
2558 out << "struct " << staticTypeClass
2559 << " : public rtl::StaticWithInit< ::css::uno::Type *, "
2560 << staticTypeClass;
2561 dumpTemplateParameters(out);
2562 out << " >\n" << indent() << "{\n";
2563 inc();
2564 out << indent() << "::css::uno::Type * operator()() const\n"
2565 << indent() << "{\n";
2566 inc();
2568 out << "#ifdef LIBO_INTERNAL_ONLY\n";
2569 out << indent()
2570 << "::rtl::OUString the_name =\n";
2571 out << indent() << "\"" << name_ << "<\" +\n";
2572 for (std::vector< OUString >::const_iterator i(
2573 entity_->getTypeParameters().begin());
2574 i != entity_->getTypeParameters().end();) {
2575 out << indent()
2576 << "::cppu::getTypeFavourChar(static_cast< ";
2577 dumpTypeParameterName(out, *i);
2578 out << " * >(0)).getTypeName() +\n";
2579 ++i;
2580 if (i != entity_->getTypeParameters().end()) {
2581 out << indent()
2582 << "\",\" +\n";
2585 out << indent()
2586 << "\">\";\n";
2587 out << "#else\n";
2588 out << indent() << "::rtl::OUStringBuffer the_buffer;\n" << indent()
2589 << "the_buffer.append(\"" << name_ << "<\");\n";
2590 for (std::vector< OUString >::const_iterator i(
2591 entity_->getTypeParameters().begin());
2592 i != entity_->getTypeParameters().end();) {
2593 out << indent()
2594 << "the_buffer.append(::cppu::getTypeFavourChar(static_cast< ";
2595 dumpTypeParameterName(out, *i);
2596 out << " * >(0)).getTypeName());\n";
2597 ++i;
2598 if (i != entity_->getTypeParameters().end()) {
2599 out << indent()
2600 << ("the_buffer.append("
2601 "static_cast< ::sal_Unicode >(','));\n");
2604 out << indent() << "the_buffer.append(static_cast< ::sal_Unicode >('>'));\n";
2605 out << indent()
2606 << "::rtl::OUString the_name(the_buffer.makeStringAndClear());\n";
2607 out << "#endif\n";
2608 std::map< OUString, sal_uInt32 > parameters;
2609 std::map< OUString, sal_uInt32 > types;
2610 std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >::
2611 size_type n = 0;
2612 for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity_->getMembers()) {
2613 if (member.parameterized) {
2614 if (parameters.emplace(
2615 member.type, static_cast< sal_uInt32 >(parameters.size())).
2616 second) {
2617 sal_uInt32 k = static_cast< sal_uInt32 >(parameters.size() - 1);
2618 out << indent()
2619 << "::css::uno::Type const & the_ptype" << k
2620 << " = ::cppu::getTypeFavourChar(static_cast< ";
2621 dumpTypeParameterName(out, member.type);
2622 out << " * >(0));\n" << indent()
2623 << "::typelib_TypeClass the_pclass" << k
2624 << " = (::typelib_TypeClass) the_ptype" << k
2625 << ".getTypeClass();\n" << indent()
2626 << "::rtl::OUString the_pname" << k << "(the_ptype" << k
2627 << ".getTypeName());\n";
2629 } else if (types.emplace(member.type, static_cast< sal_uInt32 >(types.size())).
2630 second) {
2631 dumpCppuGetType(out, member.type, &name_);
2632 // For typedefs, use the resolved type name, as there will be no
2633 // information available about the typedef itself at runtime (the
2634 // above getCppuType call will make available information about the
2635 // resolved type); no extra #include for the resolved type is
2636 // needed, as the header for the typedef includes it already:
2637 out << indent() << "::rtl::OUString the_tname"
2638 << static_cast< sal_uInt32 >(types.size() - 1) << "( \""
2639 << resolveAllTypedefs(member.type) << "\" );\n";
2641 out << indent() << "::rtl::OUString the_name" << n++ << "( \""
2642 << member.name << "\" );\n";
2644 out << indent() << "::typelib_StructMember_Init the_members[] = {\n";
2645 inc();
2646 n = 0;
2647 for (std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >::
2648 const_iterator i(entity_->getMembers().begin());
2649 i != entity_->getMembers().end();) {
2650 out << indent() << "{ { ";
2651 if (i->parameterized) {
2652 const auto iter = parameters.find(i->type);
2653 assert(iter != parameters.end());
2654 sal_uInt32 k = iter->second;
2655 out << "the_pclass" << k << ", the_pname" << k << ".pData";
2656 } else {
2657 const auto iter = types.find(i->type);
2658 assert(iter != types.end());
2659 out << getTypeClass(i->type, true) << ", the_tname"
2660 << iter->second << ".pData";
2662 out << ", the_name" << n++ << ".pData }, "
2663 << (i->parameterized ? "true" : "false") << " }";
2664 ++i;
2665 out << (i == entity_->getMembers().end() ? " };" : ",") << "\n";
2667 dec();
2668 out << indent() << "::typelib_TypeDescription * the_newType = 0;\n";
2669 out << indent()
2670 << ("::typelib_typedescription_newStruct(&the_newType, the_name.pData,"
2671 " 0, ")
2672 << entity_->getMembers().size() << ", the_members);\n" << indent()
2673 << "::typelib_typedescription_register(&the_newType);\n" << indent()
2674 << "::typelib_typedescription_release(the_newType);\n" << indent()
2675 << "return new ::css::uno::Type(" << getTypeClass(name_)
2676 << ", the_name); // leaked\n";
2677 dec();
2678 out << indent() << "}\n";
2679 dec();
2680 out << indent() << "};\n } }\n\n";
2681 dumpGetCppuTypePreamble(out);
2682 out << indent() << "return *detail::" << staticTypeClass;
2683 dumpTemplateParameters(out);
2684 out << "::get();\n";
2685 dumpGetCppuTypePostamble(out);
2688 void PolyStructType::addLightGetCppuTypeIncludes(
2689 codemaker::cppumaker::Includes & includes) const
2691 includes.addType();
2692 includes.addCppuUnotypeHxx();
2693 includes.addSalTypesH();
2694 includes.addTypelibTypeclassH();
2695 includes.addTypelibTypedescriptionH();
2696 includes.addRtlStrbufHxx();
2697 includes.addRtlTextencH();
2698 includes.addRtlUstringHxx();
2701 void PolyStructType::addNormalGetCppuTypeIncludes(
2702 codemaker::cppumaker::Includes & includes) const
2704 includes.addType();
2705 includes.addCppuUnotypeHxx();
2706 includes.addSalTypesH();
2707 includes.addTypelibTypeclassH();
2708 includes.addTypelibTypedescriptionH();
2709 includes.addRtlStrbufHxx();
2710 includes.addRtlTextencH();
2711 includes.addRtlUstringHxx();
2714 void PolyStructType::addComprehensiveGetCppuTypeIncludes(
2715 codemaker::cppumaker::Includes & includes) const
2717 includes.addType();
2718 includes.addCppuUnotypeHxx();
2719 includes.addRtlInstanceHxx();
2720 includes.addRtlUstringH();
2721 includes.addRtlUstringHxx();
2722 includes.addSalTypesH();
2723 includes.addTypelibTypeclassH();
2724 includes.addTypelibTypedescriptionH();
2725 includes.addRtlStringH();
2726 includes.addRtlUstrbufHxx();
2729 void PolyStructType::dumpTemplateHead(FileStream & out) const
2731 out << "template< ";
2732 for (std::vector< OUString >::const_iterator i(
2733 entity_->getTypeParameters().begin());
2734 i != entity_->getTypeParameters().end(); ++i) {
2735 if (i != entity_->getTypeParameters().begin()) {
2736 out << ", ";
2738 out << "typename ";
2739 dumpTypeParameterName(out, *i);
2741 out << " > ";
2744 void PolyStructType::dumpTemplateParameters(FileStream & out) const
2746 out << "< ";
2747 for (std::vector< OUString >::const_iterator i(
2748 entity_->getTypeParameters().begin());
2749 i != entity_->getTypeParameters().end(); ++i) {
2750 if (i != entity_->getTypeParameters().begin()) {
2751 out << ", ";
2753 dumpTypeParameterName(out, *i);
2755 out << " >";
2758 OUString typeToIdentifier(std::u16string_view name)
2760 sal_Int32 k;
2761 OUString n(b2u(codemaker::UnoType::decompose(u2b(name), &k)));
2762 OUStringBuffer b(4*k + n.getLength());
2763 for (sal_Int32 i = 0; i != k; ++i) {
2764 b.append("seq_");
2766 b.append(n);
2767 b.replace(' ', '_');
2768 b.replace(',', '_');
2769 b.replace('.', '_');
2770 b.replace('<', '_');
2771 b.replace('>', '_');
2772 return b.makeStringAndClear();
2775 class ExceptionType: public CppuType
2777 public:
2778 ExceptionType(
2779 rtl::Reference< unoidl::ExceptionTypeEntity > const & entity,
2780 OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
2781 CppuType(name, typeMgr), entity_(entity) {
2782 assert(entity.is());
2785 private:
2786 virtual void dumpHdlFile(
2787 FileStream & out, codemaker::cppumaker::Includes & includes) override;
2789 virtual void dumpHppFile(
2790 FileStream & out, codemaker::cppumaker::Includes & includes) override;
2792 virtual void addComprehensiveGetCppuTypeIncludes(
2793 codemaker::cppumaker::Includes & includes) const override;
2795 virtual void dumpLightGetCppuType(FileStream & out) override;
2797 virtual void dumpNormalGetCppuType(FileStream & out) override;
2799 virtual void dumpComprehensiveGetCppuType(FileStream & out) override;
2801 virtual sal_uInt32 checkInheritedMemberCount() const override {
2802 return getTotalMemberCount(entity_->getDirectBase());
2805 virtual void dumpDeclaration(FileStream & out) override;
2807 bool dumpBaseMembers(
2808 FileStream & out, OUString const & base, bool withType,
2809 bool eligibleForDefaults);
2811 sal_uInt32 getTotalMemberCount(OUString const & base) const;
2813 rtl::Reference< unoidl::ExceptionTypeEntity > entity_;
2816 void ExceptionType::dumpHdlFile(
2817 FileStream & out, codemaker::cppumaker::Includes & includes)
2819 if (name_ == "com.sun.star.uno.Exception")
2821 includes.addCustom(u"#if defined(LIBO_INTERNAL_ONLY) && !defined(NDEBUG)"_ustr);
2822 includes.addCustom(u"#if __has_include(<version>)"_ustr);
2823 includes.addCustom(u"#include <version>"_ustr);
2824 includes.addCustom(u"#endif"_ustr);
2825 includes.addCustom(u"#if defined(__cpp_lib_source_location) && __cpp_lib_source_location >= 201907"_ustr);
2826 includes.addCustom(u"#include <source_location>"_ustr);
2827 includes.addCustom(u"#define LIBO_USE_SOURCE_LOCATION std"_ustr);
2828 includes.addCustom(u"#elif __has_include(<experimental/source_location>)"_ustr);
2829 includes.addCustom(u"#include <experimental/source_location>"_ustr);
2830 includes.addCustom(u"#define LIBO_USE_SOURCE_LOCATION std::experimental"_ustr);
2831 includes.addCustom(u"#endif"_ustr);
2832 includes.addCustom(u"#endif"_ustr);
2833 includes.addCustom(u"#if defined LIBO_USE_SOURCE_LOCATION"_ustr);
2834 includes.addCustom(u"#include <o3tl/runtimetooustring.hxx>"_ustr);
2835 includes.addCustom(u"#endif"_ustr);
2837 dumpHFileContent(out, includes);
2840 void ExceptionType::addComprehensiveGetCppuTypeIncludes(
2841 codemaker::cppumaker::Includes & includes) const
2843 includes.addCppuUnotypeHxx();
2844 includes.addRtlInstanceHxx(); // using rtl::StaticWithInit
2847 void ExceptionType::dumpHppFile(
2848 FileStream & out, codemaker::cppumaker::Includes & includes)
2850 OUString headerDefine(dumpHeaderDefine(out, u"HPP"));
2851 out << "\n";
2852 addDefaultHxxIncludes(includes);
2853 includes.dump(out, &name_, true);
2855 // for the output operator below
2856 if (name_ == "com.sun.star.uno.Exception")
2858 out << "#if defined LIBO_INTERNAL_ONLY\n";
2859 out << "#include <ostream>\n";
2860 out << "#include <typeinfo>\n";
2861 out << "#endif\n";
2864 out << "\n";
2866 if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) {
2867 out << "\n";
2870 // default constructor
2871 out << "\ninline " << id_ << "::" << id_ << "(\n";
2872 out << "#if defined LIBO_USE_SOURCE_LOCATION\n";
2873 out << " LIBO_USE_SOURCE_LOCATION::source_location location\n";
2874 out << "#endif\n";
2875 out << " )\n";
2876 inc();
2877 OUString base(entity_->getDirectBase());
2878 bool bFirst = true;
2879 if (!base.isEmpty()) {
2880 out << indent() << ": " << codemaker::cpp::scopedCppName(u2b(base))
2881 << "(\n";
2882 out << "#if defined LIBO_USE_SOURCE_LOCATION\n";
2883 out << " location\n";
2884 out << "#endif\n";
2885 out << ")\n";
2886 bFirst = false;
2888 for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
2889 out << indent() << (bFirst ? ":" : ",") << " ";
2890 out << member.name;
2891 dumpInitializer(out, false, member.type);
2892 out << "\n";
2893 bFirst = false;
2895 dec();
2896 out << "{";
2897 if (!m_cppuTypeDynamic) {
2898 out << "\n";
2899 inc();
2900 dumpCppuGetType(out, name_);
2901 dec();
2902 } else {
2903 out << " ";
2905 if (name_ == "com.sun.star.uno.Exception")
2907 out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n";
2908 out << " if (!Message.isEmpty())\n";
2909 out << " Message += \" \";\n";
2910 out << " Message += \"at \" + o3tl::runtimeToOUString(location.file_name()) + \":\" + OUString::number(location.line());\n";
2911 out << "#endif\n";
2913 out << "}\n\n";
2915 // fields constructor
2916 if (!entity_->getDirectMembers().empty() || getInheritedMemberCount() > 0) {
2917 out << indent() << "inline " << id_ << "::" << id_ << "(";
2918 bFirst = !dumpBaseMembers(out, base, true, false);
2919 for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
2920 if (!bFirst) {
2921 out << ", ";
2923 dumpType(out, member.type, true, true);
2924 out << " " << member.name << "_";
2925 bFirst = false;
2927 out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n";
2928 out << " " << (bFirst ? "" : ", ") << "LIBO_USE_SOURCE_LOCATION::source_location location\n";
2929 out << "#endif\n";
2930 out << ")\n";
2931 inc();
2932 bFirst = true;
2933 if (!base.isEmpty()) {
2934 out << indent() << ": " << codemaker::cpp::scopedCppName(u2b(base))
2935 << "(";
2936 dumpBaseMembers(out, base, false, false);
2937 out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n";
2938 out << " , location\n";
2939 out << "#endif\n";
2940 out << ")\n";
2941 bFirst = false;
2943 for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
2944 out << indent() << (bFirst ? ":" : ",") << " " << member.name << "("
2945 << member.name << "_)\n";
2946 bFirst = false;
2948 dec();
2949 out << "{";
2950 if (!m_cppuTypeDynamic) {
2951 out << "\n";
2952 inc();
2953 dumpCppuGetType(out, name_);
2954 dec();
2955 } else {
2956 out << " ";
2958 if (name_ == "com.sun.star.uno.Exception")
2960 out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n";
2961 out << " if (!Message.isEmpty())\n";
2962 out << " Message += \" \";\n";
2963 out << " Message += \"at \" + o3tl::runtimeToOUString(location.file_name()) + \":\" + OUString::number(location.line());\n";
2964 out << "#endif\n";
2966 out << "}\n\n";
2968 out << "#if !defined LIBO_INTERNAL_ONLY\n" << indent() << id_ << "::" << id_
2969 << "(" << id_ << " const & the_other)";
2970 bFirst = true;
2971 if (!base.isEmpty()) {
2972 out << ": " << codemaker::cpp::scopedCppName(u2b(base))
2973 << "(the_other)";
2974 bFirst = false;
2976 for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
2977 out << (bFirst ? ":" : ",") << " " << member.name << "(the_other." << member.name
2978 << ")";
2979 bFirst = false;
2981 out << indent() << " {}\n\n" << indent() << id_ << "::~" << id_
2982 << "() {}\n\n" << indent() << id_ << " & " << id_ << "::operator =("
2983 << id_ << " const & the_other) {\n";
2984 inc();
2985 out << indent()
2986 << ("//TODO: Just like its implicitly-defined counterpart, this"
2987 " function definition is not exception-safe\n");
2988 if (!base.isEmpty()) {
2989 out << indent() << codemaker::cpp::scopedCppName(u2b(base))
2990 << "::operator =(the_other);\n";
2992 for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
2993 out << indent() << member.name << " = the_other." << member.name << ";\n";
2995 out << indent() << "return *this;\n";
2996 dec();
2997 out << indent() << "}\n#endif\n\n";
2999 // Provide an output operator for printing Exception information to SAL_WARN/SAL_INFO.
3000 if (name_ == "com.sun.star.uno.Exception")
3002 out << "#if defined LIBO_INTERNAL_ONLY\n";
3003 out << "template< typename charT, typename traits >\n";
3004 out << "inline ::std::basic_ostream<charT, traits> & operator<<(\n";
3005 out << " ::std::basic_ostream<charT, traits> & os, ::com::sun::star::uno::Exception const & exception)\n";
3006 out << "{\n";
3007 out << " // the class name is useful because exception throwing code does not always pass in a useful message\n";
3008 out << " os << typeid(exception).name();\n";
3009 out << " if (!exception.Message.isEmpty())\n";
3010 out << " os << \" msg: \" << exception.Message;\n";
3011 out << " return os;\n";
3012 out << "}\n";
3013 out << "#endif\n";
3014 out << "\n";
3017 if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) {
3018 out << "\n";
3020 out << "\n";
3022 dumpGetCppuType(out);
3023 out << "\n#endif // "<< headerDefine << "\n";
3026 void ExceptionType::dumpLightGetCppuType(FileStream & out)
3028 dumpGetCppuTypePreamble(out);
3029 out << indent()
3030 << "static typelib_TypeDescriptionReference * the_type = 0;\n"
3031 << indent() << "if ( !the_type )\n" << indent() << "{\n";
3032 inc();
3033 out << indent() << "typelib_static_type_init( &the_type, "
3034 << getTypeClass(name_, true) << ", \"" << name_ << "\" );\n";
3035 dec();
3036 out << indent() << "}\n" << indent()
3037 << ("return * reinterpret_cast< ::css::uno::Type * >("
3038 " &the_type );\n");
3039 dumpGetCppuTypePostamble(out);
3042 void ExceptionType::dumpNormalGetCppuType(FileStream & out)
3044 dumpGetCppuTypePreamble(out);
3045 out << indent()
3046 << "static typelib_TypeDescriptionReference * the_type = 0;\n"
3047 << indent() << "if ( !the_type )\n" << indent() << "{\n";
3048 inc();
3049 OUString base(entity_->getDirectBase());
3050 bool baseException = false;
3051 if (!base.isEmpty()) {
3052 if (base == "com.sun.star.uno.Exception") {
3053 baseException = true;
3054 } else {
3055 out << indent()
3056 << ("const ::css::uno::Type& rBaseType ="
3057 " ::cppu::UnoType< ");
3058 dumpType(out, base, true, false, false, true);
3059 out << " >::get();\n\n";
3062 if (!entity_->getDirectMembers().empty()) {
3063 out << indent() << "typelib_TypeDescriptionReference * aMemberRefs["
3064 << entity_->getDirectMembers().size() << "];\n";
3065 std::set< OUString > seen;
3066 std::vector< unoidl::ExceptionTypeEntity::Member >::size_type n = 0;
3067 for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
3068 OUString type(resolveAllTypedefs(member.type));
3069 OUString modType(typeToIdentifier(type));
3070 if (seen.insert(type).second) {
3071 out << indent()
3072 << "const ::css::uno::Type& rMemberType_"
3073 << modType << " = ::cppu::UnoType< ";
3074 dumpType(out, type, false, false, false, true);
3075 out << " >::get();\n";
3077 out << indent() << "aMemberRefs[" << n++ << "] = rMemberType_"
3078 << modType << ".getTypeLibType();\n";
3080 out << "\n";
3082 out << indent() << "typelib_static_compound_type_init( &the_type, "
3083 << getTypeClass(name_, true) << ", \"" << name_ << "\", ";
3084 if (baseException) {
3085 out << ("* ::typelib_static_type_getByTypeClass("
3086 " typelib_TypeClass_EXCEPTION )");
3087 } else if (base.isEmpty()) {
3088 out << "0";
3089 } else {
3090 out << "rBaseType.getTypeLibType()";
3092 out << ", " << entity_->getDirectMembers().size() << ", "
3093 << (entity_->getDirectMembers().empty() ? "0" : "aMemberRefs")
3094 << " );\n";
3095 dec();
3096 out << indent() << "}\n" << indent()
3097 << ("return * reinterpret_cast< const ::css::uno::Type * >("
3098 " &the_type );\n");
3099 dumpGetCppuTypePostamble(out);
3102 void ExceptionType::dumpComprehensiveGetCppuType(FileStream & out)
3104 codemaker::cppumaker::dumpNamespaceOpen(out, name_, false);
3105 out << " namespace detail {\n\n";
3106 OUString staticTypeClass("the" + id_ + "Type");
3107 out << indent() << "struct " << staticTypeClass
3108 << " : public rtl::StaticWithInit< ::css::uno::Type *, "
3109 << staticTypeClass << " >\n" << indent() << "{\n";
3110 inc();
3111 out << indent() << "::css::uno::Type * operator()() const\n"
3112 << indent() << "{\n";
3113 inc();
3114 out << indent() << "::rtl::OUString sTypeName( \"" << name_ << "\" );\n\n"
3115 << indent() << "// Start inline typedescription generation\n"
3116 << indent() << "typelib_TypeDescription * pTD = 0;\n";
3117 OUString base(entity_->getDirectBase());
3118 if (!base.isEmpty()) {
3119 out << indent()
3120 << ("const ::css::uno::Type& rSuperType ="
3121 " ::cppu::UnoType< ");
3122 dumpType(out, base, false, false, false, true);
3123 out << " >::get();\n";
3125 std::set< OUString > seen;
3126 for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
3127 if (seen.insert(member.type).second) {
3128 dumpCppuGetType(out, member.type);
3131 if (!entity_->getDirectMembers().empty()) {
3132 out << "\n" << indent() << "typelib_CompoundMember_Init aMembers["
3133 << entity_->getDirectMembers().size() << "];\n";
3134 std::vector< unoidl::ExceptionTypeEntity::Member >::size_type n = 0;
3135 for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
3136 OUString type(resolveAllTypedefs(member.type));
3137 out << indent() << "::rtl::OUString sMemberType" << n << "( \""
3138 << type << "\" );\n" << indent()
3139 << "::rtl::OUString sMemberName" << n << "( \"" << member.name
3140 << "\" );\n" << indent() << "aMembers[" << n
3141 << "].eTypeClass = (typelib_TypeClass)" << getTypeClass(type)
3142 << ";\n" << indent() << "aMembers[" << n
3143 << "].pTypeName = sMemberType" << n << ".pData;\n" << indent()
3144 << "aMembers[" << n << "].pMemberName = sMemberName" << n
3145 << ".pData;\n";
3146 ++n;
3149 out << "\n" << indent() << "typelib_typedescription_new(\n";
3150 inc();
3151 out << indent() << "&pTD,\n" << indent() << "(typelib_TypeClass)"
3152 << getTypeClass(name_) << ", sTypeName.pData,\n" << indent()
3153 << (base.isEmpty() ? "0" : "rSuperType.getTypeLibType()") << ",\n"
3154 << indent() << entity_->getDirectMembers().size() << ",\n" << indent()
3155 << (entity_->getDirectMembers().empty() ? "0" : "aMembers")
3156 << " );\n\n";
3157 dec();
3158 out << indent()
3159 << ("typelib_typedescription_register( (typelib_TypeDescription**)&pTD"
3160 " );\n\n")
3161 << indent() << "typelib_typedescription_release( pTD );\n" << indent()
3162 << "// End inline typedescription generation\n\n" << indent()
3163 << "return new ::css::uno::Type( " << getTypeClass(name_)
3164 << ", sTypeName ); // leaked\n";
3165 dec();
3166 out << indent() << "}\n";
3167 dec();
3168 out << indent() << "};\n\n";
3169 codemaker::cppumaker::dumpNamespaceClose(out, name_, false);
3170 out << " }\n\n";
3171 dumpGetCppuTypePreamble(out);
3172 out << indent() << "return *detail::" << staticTypeClass << "::get();\n";
3173 dumpGetCppuTypePostamble(out);
3176 void ExceptionType::dumpDeclaration(FileStream & out)
3178 out << "\nclass CPPU_GCC_DLLPUBLIC_EXPORT SAL_WARN_UNUSED " << id_;
3179 OUString base(entity_->getDirectBase());
3180 if (!base.isEmpty()) {
3181 out << " : public " << codemaker::cpp::scopedCppName(u2b(base));
3183 out << "\n{\npublic:\n";
3184 inc();
3186 // default constructor
3187 out << indent() << "inline CPPU_GCC_DLLPRIVATE " << id_ << "(\n";
3188 out << "#if defined LIBO_USE_SOURCE_LOCATION\n";
3189 out << " LIBO_USE_SOURCE_LOCATION::source_location location = LIBO_USE_SOURCE_LOCATION::source_location::current()\n";
3190 out << "#endif\n\n";
3191 out << " );\n";
3193 // constructor that initializes data members
3194 if (!entity_->getDirectMembers().empty() || getInheritedMemberCount() > 0) {
3195 out << indent() << "inline CPPU_GCC_DLLPRIVATE " << id_ << "(";
3196 bool eligibleForDefaults = entity_->getDirectMembers().empty();
3197 bool bFirst = !dumpBaseMembers(out, base, true, eligibleForDefaults);
3198 for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
3199 if (!bFirst) {
3200 out << ", ";
3202 dumpType(out, member.type, true, true);
3203 out << " " << member.name << "_";
3204 bFirst = false;
3206 out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n";
3207 out << ", LIBO_USE_SOURCE_LOCATION::source_location location = LIBO_USE_SOURCE_LOCATION::source_location::current()\n";
3208 out << "#endif\n";
3209 out << " );\n\n";
3211 out << "#if !defined LIBO_INTERNAL_ONLY\n" << indent()
3212 << "inline CPPU_GCC_DLLPRIVATE " << id_ << "(" << id_
3213 << " const &);\n\n" << indent() << "inline CPPU_GCC_DLLPRIVATE ~"
3214 << id_ << "();\n\n" << indent() << "inline CPPU_GCC_DLLPRIVATE " << id_
3215 << " & operator =(" << id_ << " const &);\n#endif\n\n";
3216 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
3217 entity_->getDirectMembers().begin());
3218 i != entity_->getDirectMembers().end(); ++i) {
3219 out << indent();
3220 dumpType(out, i->type);
3221 out << " " << i->name;
3222 if (i == entity_->getDirectMembers().begin() && !base.isEmpty()
3223 && i->type != "hyper" && i->type != "unsigned hyper"
3224 && i->type != "double") {
3225 out << " CPPU_GCC3_ALIGN( "
3226 << codemaker::cpp::scopedCppName(u2b(base)) << " )";
3228 out << ";\n";
3230 dec();
3231 out << "};\n\n";
3234 bool ExceptionType::dumpBaseMembers(
3235 FileStream & out, OUString const & base, bool withType, bool eligibleForDefaults)
3237 if (base.isEmpty())
3238 return false;
3240 bool hasMember = false;
3241 rtl::Reference< unoidl::Entity > ent;
3242 codemaker::UnoType::Sort sort = m_typeMgr->getSort(base, &ent);
3243 if (sort != codemaker::UnoType::Sort::Exception) {
3244 throw CannotDumpException(
3245 "exception type base " + base + " is not an exception type");
3247 rtl::Reference< unoidl::ExceptionTypeEntity > ent2(
3248 dynamic_cast< unoidl::ExceptionTypeEntity * >(ent.get()));
3249 assert(ent2.is());
3250 if (!ent2.is()) {
3251 return false;
3253 hasMember = dumpBaseMembers( out, ent2->getDirectBase(), withType,
3254 eligibleForDefaults && ent2->getDirectMembers().empty() );
3255 int memberCount = 0;
3256 for (const unoidl::ExceptionTypeEntity::Member& member : ent2->getDirectMembers()) {
3257 if (hasMember) {
3258 out << ", ";
3260 if (withType) {
3261 dumpType(out, member.type, true, true);
3262 out << " ";
3264 out << member.name << "_";
3265 // We want to provide a default parameter value for uno::Exception subtype
3266 // constructors, since most of the time we don't pass a Context object in to the exception
3267 // throw sites.
3268 if (eligibleForDefaults
3269 && base == "com.sun.star.uno.Exception"
3270 && memberCount == 1
3271 && member.name == "Context"
3272 && member.type == "com.sun.star.uno.XInterface") {
3273 out << " = ::css::uno::Reference< ::css::uno::XInterface >()";
3275 hasMember = true;
3276 ++memberCount;
3278 return hasMember;
3281 sal_uInt32 ExceptionType::getTotalMemberCount(OUString const & base) const
3283 if (base.isEmpty()) {
3284 return 0;
3286 rtl::Reference< unoidl::Entity > ent;
3287 codemaker::UnoType::Sort sort = m_typeMgr->getSort(base, &ent);
3288 if (sort != codemaker::UnoType::Sort::Exception) {
3289 throw CannotDumpException(
3290 "exception type base " + base + " is not an exception type");
3292 unoidl::ExceptionTypeEntity& ent2(dynamic_cast<unoidl::ExceptionTypeEntity&>(*ent));
3293 return getTotalMemberCount(ent2.getDirectBase())
3294 + ent2.getDirectMembers().size(); //TODO: overflow
3297 class EnumType: public CppuType
3299 public:
3300 EnumType(
3301 rtl::Reference< unoidl::EnumTypeEntity > const & entity,
3302 OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
3303 CppuType(name, typeMgr), entity_(entity) {
3304 assert(entity.is());
3307 private:
3308 virtual void dumpDeclaration(FileStream& o) override;
3310 virtual void addComprehensiveGetCppuTypeIncludes(
3311 codemaker::cppumaker::Includes & includes) const override;
3313 void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
3315 void dumpNormalGetCppuType(FileStream& o) override;
3316 void dumpComprehensiveGetCppuType(FileStream& o) override;
3318 rtl::Reference< unoidl::EnumTypeEntity > entity_;
3321 void EnumType::addComprehensiveGetCppuTypeIncludes(
3322 codemaker::cppumaker::Includes & includes) const
3324 includes.addCppuUnotypeHxx();
3325 includes.addRtlInstanceHxx(); // using rtl::StaticWithInit
3328 void EnumType::dumpDeclaration(FileStream& o)
3330 o << "\n#if defined LIBO_INTERNAL_ONLY\n";
3331 o << "\n#if defined __GNUC__\n"; // gcc does not like visibility annotation on enum
3332 o << "\nenum class " << id_ << "\n{\n";
3333 o << "\n#else\n";
3334 o << "\nenum class SAL_DLLPUBLIC_RTTI " << id_ << "\n{\n";
3335 o << "\n#endif\n";
3336 o << "\n#else\n";
3337 o << "\nenum SAL_DLLPUBLIC_RTTI " << id_ << "\n{\n";
3338 o << "\n#endif\n";
3339 inc();
3341 for (const unoidl::EnumTypeEntity::Member& member : entity_->getMembers()) {
3342 o << indent() << id_ << "_" << u2b(member.name) << " = " << member.value
3343 << ",\n";
3346 o << indent() << id_ << "_MAKE_FIXED_SIZE = SAL_MAX_ENUM\n";
3348 dec();
3349 o << "};\n\n";
3351 // use constexpr to create a kind of type-alias so we don't have to modify existing code
3352 o << "#if defined LIBO_INTERNAL_ONLY\n";
3353 for (const unoidl::EnumTypeEntity::Member& member : entity_->getMembers()) {
3354 o << "constexpr auto " << id_ << "_" << u2b(member.name)
3355 << " = "
3356 << id_ << "::" << id_ << "_" << u2b(member.name)
3357 << ";\n";
3359 o << "#endif\n";
3362 void EnumType::dumpHppFile(
3363 FileStream& o, codemaker::cppumaker::Includes & includes)
3365 OUString headerDefine(dumpHeaderDefine(o, u"HPP"));
3366 o << "\n";
3368 addDefaultHxxIncludes(includes);
3369 includes.dump(o, &name_, true);
3370 o << "\n";
3372 dumpGetCppuType(o);
3374 o << "\n#endif // "<< headerDefine << "\n";
3377 void EnumType::dumpNormalGetCppuType(FileStream& o)
3379 dumpGetCppuTypePreamble(o);
3381 o << indent()
3382 << "static typelib_TypeDescriptionReference * the_type = 0;\n";
3384 o << indent() << "if ( !the_type )\n" << indent() << "{\n";
3385 inc();
3387 o << indent() << "typelib_static_enum_type_init( &the_type,\n";
3388 inc(31);
3389 o << indent() << "\"" << name_ << "\",\n"
3390 << indent() << codemaker::cpp::scopedCppName(u2b(name_)) << "_"
3391 << u2b(entity_->getMembers()[0].name) << " );\n";
3392 dec(31);
3393 dec();
3394 o << indent() << "}\n";
3395 o << indent()
3396 << ("return * reinterpret_cast< ::css::uno::Type * >("
3397 " &the_type );\n");
3398 dumpGetCppuTypePostamble(o);
3401 void EnumType::dumpComprehensiveGetCppuType(FileStream& o)
3403 if (!isPolymorphic())
3404 codemaker::cppumaker::dumpNamespaceOpen(o, name_, false);
3405 else
3406 o << "namespace cppu { ";
3407 o << " namespace detail {\n\n";
3409 OUString sStaticTypeClass("the" + id_ + "Type");
3410 o << indent() << "struct " << sStaticTypeClass << " : public rtl::StaticWithInit< ::css::uno::Type *, " << sStaticTypeClass << " >\n";
3411 o << indent() << "{\n";
3412 inc();
3413 o << indent() << "::css::uno::Type * operator()() const\n";
3414 o << indent() << "{\n";
3416 inc();
3417 o << indent() << "::rtl::OUString sTypeName( \"" << name_
3418 << "\" );\n\n";
3420 o << indent() << "// Start inline typedescription generation\n"
3421 << indent() << "typelib_TypeDescription * pTD = 0;\n\n";
3423 o << indent() << "rtl_uString* enumValueNames["
3424 << entity_->getMembers().size() << "];\n";
3425 std::vector< unoidl::EnumTypeEntity::Member >::size_type n = 0;
3426 for (const unoidl::EnumTypeEntity::Member& member : entity_->getMembers()) {
3427 o << indent() << "::rtl::OUString sEnumValue" << n << "( \""
3428 << u2b(member.name) << "\" );\n";
3429 o << indent() << "enumValueNames[" << n << "] = sEnumValue" << n
3430 << ".pData;\n";
3431 ++n;
3434 o << "\n" << indent() << "sal_Int32 enumValues["
3435 << entity_->getMembers().size() << "];\n";
3436 n = 0;
3437 for (const unoidl::EnumTypeEntity::Member& member : entity_->getMembers()) {
3438 o << indent() << "enumValues[" << n++ << "] = " << member.value << ";\n";
3441 o << "\n" << indent() << "typelib_typedescription_newEnum( &pTD,\n";
3442 inc();
3443 o << indent() << "sTypeName.pData,\n"
3444 << indent() << "(sal_Int32)"
3445 << codemaker::cpp::scopedCppName(u2b(name_), false) << "_"
3446 << u2b(entity_->getMembers()[0].name) << ",\n"
3447 << indent() << entity_->getMembers().size()
3448 << ", enumValueNames, enumValues );\n\n";
3449 dec();
3451 o << indent()
3452 << ("typelib_typedescription_register( (typelib_TypeDescription**)&pTD"
3453 " );\n");
3454 o << indent() << "typelib_typedescription_release( pTD );\n"
3455 << indent() << "// End inline typedescription generation\n\n";
3457 o << indent() << "return new ::css::uno::Type( "
3458 << getTypeClass(name_) << ", sTypeName ); // leaked\n";
3460 dec();
3461 o << indent() << "}\n";
3462 dec();
3463 o << indent() << "};\n\n";
3465 if (!isPolymorphic())
3466 codemaker::cppumaker::dumpNamespaceClose(o, name_, false);
3467 else
3468 o << " }";
3469 o << " }\n\n";
3471 dumpGetCppuTypePreamble(o);
3472 o << indent() << "return *detail::" << sStaticTypeClass << "::get();\n";
3473 dumpGetCppuTypePostamble(o);
3476 class Typedef: public CppuType
3478 public:
3479 Typedef(
3480 rtl::Reference< unoidl::TypedefEntity > const & entity,
3481 OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
3482 CppuType(name, typeMgr), entity_(entity) {
3483 assert(entity.is());
3486 private:
3487 virtual void dumpDeclaration(FileStream& o) override;
3489 void dumpHdlFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
3491 void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
3493 rtl::Reference< unoidl::TypedefEntity > entity_;
3496 void Typedef::dumpHdlFile(
3497 FileStream& o, codemaker::cppumaker::Includes & includes)
3499 OUString headerDefine(dumpHeaderDefine(o, u"HDL"));
3500 o << "\n";
3502 addDefaultHIncludes(includes);
3503 includes.dump(o, nullptr, true);
3504 o << "\n";
3506 if (codemaker::cppumaker::dumpNamespaceOpen(o, name_, false)) {
3507 o << "\n";
3510 dumpDeclaration(o);
3512 if (codemaker::cppumaker::dumpNamespaceClose(o, name_, false)) {
3513 o << "\n";
3516 o << "#endif // "<< headerDefine << "\n";
3519 void Typedef::dumpDeclaration(FileStream& o)
3521 o << "\ntypedef ";
3522 dumpType(o, entity_->getType());
3523 o << " " << id_ << ";\n\n";
3526 void Typedef::dumpHppFile(
3527 FileStream& o, codemaker::cppumaker::Includes & includes)
3529 OUString headerDefine(dumpHeaderDefine(o, u"HPP"));
3530 o << "\n";
3532 addDefaultHxxIncludes(includes);
3533 includes.dump(o, &name_, true);
3534 o << "\n";
3536 o << "\n#endif // "<< headerDefine << "\n";
3539 class ConstructiveType: public CppuType
3541 public:
3542 ConstructiveType(
3543 OUString const & name, rtl::Reference< TypeManager > const & manager):
3544 CppuType(name, manager) {}
3546 private:
3547 virtual void dumpHdlFile(FileStream &, codemaker::cppumaker::Includes &) override {
3548 assert(false); // this cannot happen
3551 virtual void dumpFiles(OUString const & uri, CppuOptions const & options) override {
3552 dumpFile(uri, name_, FileType::HPP, options);
3556 bool hasRestParameter(
3557 unoidl::SingleInterfaceBasedServiceEntity::Constructor const & constructor)
3559 return !constructor.parameters.empty()
3560 && constructor.parameters.back().rest;
3563 void includeExceptions(
3564 codemaker::cppumaker::Includes & includes,
3565 codemaker::ExceptionTreeNode const * node)
3567 if (node->present) {
3568 includes.add(node->name);
3569 } else {
3570 for (std::unique_ptr<codemaker::ExceptionTreeNode> const & pChild : node->children) {
3571 includeExceptions(includes, pChild.get());
3576 class ServiceType: public ConstructiveType
3578 public:
3579 ServiceType(
3580 rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > const &
3581 entity,
3582 OUString const & name, rtl::Reference< TypeManager > const & manager):
3583 ConstructiveType(name, manager), entity_(entity) {
3584 assert(entity.is());
3587 private:
3588 virtual void dumpHppFile(
3589 FileStream & o, codemaker::cppumaker::Includes & includes) override;
3591 void dumpCatchClauses(
3592 FileStream & out, codemaker::ExceptionTreeNode const * node);
3594 rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > entity_;
3597 void failsToSupply(
3598 FileStream & o, std::u16string_view service, OString const & type)
3600 o << "::rtl::OUString(\"component context fails to supply service \") + \""
3601 << service << "\" + \" of type \" + \"" << type << "\"";
3604 void ServiceType::dumpHppFile(
3605 FileStream & o, codemaker::cppumaker::Includes & includes)
3607 if (!entity_->getConstructors().empty()) {
3608 //TODO: Decide whether the types added to includes should rather be
3609 // added to m_dependencies (and thus be generated during
3610 // dumpDependedTypes):
3611 includes.addCassert();
3612 includes.addReference();
3613 includes.addRtlUstringH();
3614 includes.addRtlUstringHxx();
3615 includes.add("com.sun.star.uno.DeploymentException"_ostr);
3616 includes.add("com.sun.star.uno.XComponentContext"_ostr);
3617 for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor& cons : entity_->getConstructors()) {
3618 if (cons.defaultConstructor) {
3619 includes.add("com.sun.star.uno.Exception"_ostr);
3620 includes.add("com.sun.star.uno.RuntimeException"_ostr);
3621 } else {
3622 if (!hasRestParameter(cons)) {
3623 includes.addAny();
3624 includes.addSequence();
3625 for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter& param :
3626 cons.parameters) {
3627 if (m_typeMgr->getSort(
3628 b2u(codemaker::UnoType::decompose(
3629 u2b(param.type))))
3630 == codemaker::UnoType::Sort::Char) {
3631 includes.addCppuUnotypeHxx();
3632 break;
3636 codemaker::ExceptionTree tree;
3637 for (const OUString& ex : cons.exceptions) {
3638 tree.add(u2b(ex), m_typeMgr);
3640 if (!tree.getRoot().present) {
3641 includes.add("com.sun.star.uno.Exception"_ostr);
3642 includes.add("com.sun.star.uno.RuntimeException"_ostr);
3643 includeExceptions(includes, &tree.getRoot());
3648 OString cppName(
3649 codemaker::cpp::translateUnoToCppIdentifier(
3650 u2b(id_), "service", isGlobal()));
3651 OUString headerDefine(dumpHeaderDefine(o, u"HPP"));
3652 o << "\n";
3653 includes.dump(o, nullptr, true);
3654 if (!entity_->getConstructors().empty()) {
3655 o << ("\n#if defined ANDROID || defined IOS //TODO\n"
3656 "#include <com/sun/star/lang/XInitialization.hpp>\n"
3657 "#include <osl/detail/component-defines.h>\n#endif\n\n"
3658 "#if defined LO_URE_CURRENT_ENV && defined LO_URE_CTOR_ENV_")
3659 << name_.replaceAll(".", "_dot_")
3660 << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_"
3661 << name_.replaceAll(".", "_dot_") << ") && defined LO_URE_CTOR_FUN_"
3662 << name_.replaceAll(".", "_dot_")
3663 << "\nextern \"C\" ::css::uno::XInterface * SAL_CALL LO_URE_CTOR_FUN_"
3664 << name_.replaceAll(".", "_dot_")
3665 << "(::css::uno::XComponentContext *, ::css::uno::Sequence< "
3666 "::css::uno::Any > const &);\n#endif\n";
3668 o << "\n";
3669 if (codemaker::cppumaker::dumpNamespaceOpen(o, name_, false)) {
3670 o << "\n";
3672 o << "\nclass " << cppName << " {\n";
3673 inc();
3674 if (!entity_->getConstructors().empty()) {
3675 OString baseName(u2b(entity_->getBase()));
3676 OString scopedBaseName(codemaker::cpp::scopedCppName(baseName));
3677 o << "public:\n";
3678 for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor& cons :
3679 entity_->getConstructors()) {
3680 if (cons.defaultConstructor) {
3681 o << indent() << "static ::css::uno::Reference< "
3682 << scopedBaseName << " > "
3683 << codemaker::cpp::translateUnoToCppIdentifier(
3684 "create"_ostr, "method", codemaker::cpp::IdentifierTranslationMode::NonGlobal,
3685 &cppName)
3686 << ("(::css::uno::Reference< ::css::uno::XComponentContext > const &"
3687 " the_context) {\n");
3688 inc();
3689 o << indent() << "assert(the_context.is());\n" << indent()
3690 << "::css::uno::Reference< " << scopedBaseName
3691 << " > the_instance;\n" << indent() << "try {\n";
3692 inc();
3693 o << ("#if defined LO_URE_CURRENT_ENV && defined "
3694 "LO_URE_CTOR_ENV_")
3695 << name_.replaceAll(".", "_dot_")
3696 << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_"
3697 << name_.replaceAll(".", "_dot_")
3698 << ") && defined LO_URE_CTOR_FUN_"
3699 << name_.replaceAll(".", "_dot_") << "\n" << indent()
3700 << "the_instance = ::css::uno::Reference< " << scopedBaseName
3701 << (" >(::css::uno::Reference< ::css::uno::XInterface >("
3702 "static_cast< ::css::uno::XInterface * >((*"
3703 "LO_URE_CTOR_FUN_")
3704 << name_.replaceAll(".", "_dot_")
3705 << (")(the_context.get(), ::css::uno::Sequence<"
3706 " ::css::uno::Any >())), ::SAL_NO_ACQUIRE),"
3707 " ::css::uno::UNO_QUERY);\n#else\n")
3708 << indent() << "the_instance = ::css::uno::Reference< "
3709 << scopedBaseName
3710 << (" >(the_context->getServiceManager()->"
3711 "createInstanceWithContext("
3712 " \"")
3713 << name_
3714 << "\", the_context), ::css::uno::UNO_QUERY);\n#endif\n";
3715 dec();
3716 o << indent()
3717 << "} catch (const ::css::uno::RuntimeException &) {\n";
3718 inc();
3719 o << indent() << "throw;\n";
3720 dec();
3721 o << indent()
3722 << "} catch (const ::css::uno::Exception & the_exception) {\n";
3723 inc();
3724 o << indent() << "throw ::css::uno::DeploymentException(";
3725 failsToSupply(o, name_, baseName);
3726 o << " + \": \" + the_exception.Message, the_context);\n";
3727 dec();
3728 o << indent() << "}\n" << indent()
3729 << "if (!the_instance.is()) {\n";
3730 inc();
3731 o << indent() << "throw ::css::uno::DeploymentException(";
3732 failsToSupply(o, name_, baseName);
3733 o << ", the_context);\n";
3734 dec();
3735 o << indent() << "}\n" << indent() << "return the_instance;\n";
3736 dec();
3737 o << indent() << "}\n\n";
3738 } else {
3739 o << indent() << "static ::css::uno::Reference< "
3740 << scopedBaseName << " > "
3741 << codemaker::cpp::translateUnoToCppIdentifier(
3742 u2b(cons.name), "method", codemaker::cpp::IdentifierTranslationMode::NonGlobal,
3743 &cppName)
3744 << ("(::css::uno::Reference< ::css::uno::XComponentContext > const &"
3745 " the_context");
3746 bool rest = hasRestParameter(cons);
3747 for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter& param :
3748 cons.parameters) {
3749 o << ", ";
3750 OUStringBuffer buf(2 + param.type.getLength());
3751 if (param.rest) {
3752 buf.append("[]");
3754 buf.append(param.type);
3755 OUString type(buf.makeStringAndClear());
3756 bool byRef = passByReference(type);
3757 dumpType(o, type, byRef, byRef);
3758 o << " "
3759 << codemaker::cpp::translateUnoToCppIdentifier(
3760 u2b(param.name), "param", codemaker::cpp::IdentifierTranslationMode::NonGlobal);
3762 o << ") {\n";
3763 inc();
3764 o << indent() << "assert(the_context.is());\n";
3765 if (!rest && !cons.parameters.empty()) {
3766 o << indent()
3767 << "::css::uno::Sequence< ::css::uno::Any > the_arguments("
3768 << cons.parameters.size() << ");\n";
3769 o << indent()
3770 << "::css::uno::Any* the_arguments_array = the_arguments.getArray();\n";
3772 std::vector<
3773 unoidl::SingleInterfaceBasedServiceEntity::Constructor::
3774 Parameter >::size_type n = 0;
3775 for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter& j :
3776 cons.parameters) {
3777 o << indent() << "the_arguments_array[" << n++ << "] ";
3778 OString param(
3779 codemaker::cpp::translateUnoToCppIdentifier(
3780 u2b(j.name), "param",
3781 codemaker::cpp::IdentifierTranslationMode::NonGlobal));
3782 sal_Int32 rank;
3783 if (resolveOuterTypedefs(j.type) == "any") {
3784 o << "= " << param;
3785 } else if (m_typeMgr->getSort(
3786 b2u(codemaker::UnoType::decompose(
3787 u2b(j.type), &rank)))
3788 == codemaker::UnoType::Sort::Char) {
3789 o << "= ::css::uno::Any(&" << param
3790 << ", ::cppu::UnoType< ";
3791 for (sal_Int32 k = 0; k < rank; ++k) {
3792 o << "::cppu::UnoSequenceType< ";
3794 o << "::cppu::UnoCharType";
3795 for (sal_Int32 k = 0; k < rank; ++k) {
3796 o << " >";
3798 o << " >::get())";
3799 } else {
3800 o << "<<= " << param;
3802 o << ";\n";
3805 o << indent() << "::css::uno::Reference< "
3806 << scopedBaseName << " > the_instance;\n";
3807 codemaker::ExceptionTree tree;
3808 for (const OUString& ex : cons.exceptions) {
3809 tree.add(u2b(ex), m_typeMgr);
3811 if (!tree.getRoot().present) {
3812 o << indent() << "try {\n";
3813 inc();
3815 o << ("#if defined LO_URE_CURRENT_ENV && defined "
3816 "LO_URE_CTOR_ENV_")
3817 << name_.replaceAll(".", "_dot_")
3818 << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_"
3819 << name_.replaceAll(".", "_dot_")
3820 << ") && defined LO_URE_CTOR_FUN_"
3821 << name_.replaceAll(".", "_dot_") << "\n" << indent()
3822 << "the_instance = ::css::uno::Reference< " << scopedBaseName
3823 << (" >(::css::uno::Reference< ::css::uno::XInterface >("
3824 "static_cast< ::css::uno::XInterface * >((*"
3825 "LO_URE_CTOR_FUN_")
3826 << name_.replaceAll(".", "_dot_")
3827 << ")(the_context.get(), ";
3828 if (rest) {
3829 o << codemaker::cpp::translateUnoToCppIdentifier(
3830 u2b(cons.parameters.back().name), "param",
3831 codemaker::cpp::IdentifierTranslationMode::NonGlobal);
3832 } else if (cons.parameters.empty()) {
3833 o << "::css::uno::Sequence< ::css::uno::Any >()";
3834 } else {
3835 o << "the_arguments";
3837 o << ")), ::SAL_NO_ACQUIRE), ::css::uno::UNO_QUERY);\n" << indent()
3838 << ("::css::uno::Reference< ::css::lang::XInitialization > "
3839 "init(the_instance, ::css::uno::UNO_QUERY);\n")
3840 << indent() << "if (init.is()) {\n"
3841 << indent() << " init->initialize(";
3842 if (cons.parameters.empty()) {
3843 o << "::css::uno::Sequence< ::css::uno::Any >()";
3844 } else {
3845 o << "the_arguments";
3847 o << ");\n" << indent() << "}\n";
3848 o << "#else\n"
3849 << indent() << "the_instance = ::css::uno::Reference< "
3850 << scopedBaseName
3851 << (" >(the_context->getServiceManager()->"
3852 "createInstanceWithArgumentsAndContext("
3853 " \"")
3854 << name_ << "\", ";
3855 if (rest) {
3856 o << codemaker::cpp::translateUnoToCppIdentifier(
3857 u2b(cons.parameters.back().name), "param",
3858 codemaker::cpp::IdentifierTranslationMode::NonGlobal);
3859 } else if (cons.parameters.empty()) {
3860 o << "::css::uno::Sequence< ::css::uno::Any >()";
3861 } else {
3862 o << "the_arguments";
3864 o << ", the_context), ::css::uno::UNO_QUERY);\n#endif\n";
3865 if (!tree.getRoot().present) {
3866 dec();
3867 o << indent()
3868 << "} catch (const ::css::uno::RuntimeException &) {\n";
3869 inc();
3870 o << indent() << "throw;\n";
3871 dec();
3872 dumpCatchClauses(o, &tree.getRoot());
3873 o << indent()
3874 << ("} catch (const ::css::uno::Exception &"
3875 " the_exception) {\n");
3876 inc();
3877 o << indent() << "throw ::css::uno::DeploymentException(";
3878 failsToSupply(o, name_, baseName);
3879 o << " + \": \" + the_exception.Message, the_context);\n";
3880 dec();
3881 o << indent() << "}\n";
3883 o << indent() << "if (!the_instance.is()) {\n";
3884 inc();
3885 o << indent() << "throw ::css::uno::DeploymentException(";
3886 failsToSupply(o, name_, baseName);
3887 o << ", the_context);\n";
3888 dec();
3889 o << indent() << "}\n" << indent() << "return the_instance;\n";
3890 dec();
3891 o << indent() << "}\n\n";
3895 o << "private:\n";
3896 o << indent() << cppName << "(); // not implemented\n"
3897 << indent() << cppName << "(" << cppName << " &); // not implemented\n"
3898 << indent() << "~" << cppName << "(); // not implemented\n"
3899 << indent() << "void operator =(" << cppName << "); // not implemented\n";
3900 dec();
3901 o << "};\n\n";
3902 if (codemaker::cppumaker::dumpNamespaceClose(o, name_, false)) {
3903 o << "\n";
3905 o << "\n#endif // "<< headerDefine << "\n";
3908 void ServiceType::dumpCatchClauses(
3909 FileStream & out, codemaker::ExceptionTreeNode const * node)
3911 if (node->present) {
3912 out << indent() << "} catch (const ";
3913 dumpType(out, b2u(node->name));
3914 out << " &) {\n";
3915 inc();
3916 out << indent() << "throw;\n";
3917 dec();
3918 } else {
3919 for (std::unique_ptr<codemaker::ExceptionTreeNode> const & pChild : node->children) {
3920 dumpCatchClauses(out, pChild.get());
3925 class SingletonType: public ConstructiveType
3927 public:
3928 SingletonType(
3929 rtl::Reference< unoidl::InterfaceBasedSingletonEntity > const & entity,
3930 OUString const & name, rtl::Reference< TypeManager > const & manager):
3931 ConstructiveType(name, manager), entity_(entity) {
3932 assert(entity.is());
3935 private:
3936 virtual void dumpHppFile(
3937 FileStream & o, codemaker::cppumaker::Includes & includes) override;
3939 rtl::Reference< unoidl::InterfaceBasedSingletonEntity > entity_;
3942 void SingletonType::dumpHppFile(
3943 FileStream & o, codemaker::cppumaker::Includes & includes)
3945 OString cppName(
3946 codemaker::cpp::translateUnoToCppIdentifier(
3947 u2b(id_), "singleton", isGlobal()));
3948 OString baseName(u2b(entity_->getBase()));
3949 OString scopedBaseName(codemaker::cpp::scopedCppName(baseName));
3950 OUString headerDefine(dumpHeaderDefine(o, u"HPP"));
3951 o << "\n";
3952 //TODO: Decide whether the types added to includes should rather be added to
3953 // m_dependencies (and thus be generated during dumpDependedTypes):
3954 includes.add("com.sun.star.uno.DeploymentException"_ostr);
3955 includes.add("com.sun.star.uno.XComponentContext"_ostr);
3956 includes.addCassert();
3957 includes.addAny();
3958 includes.addReference();
3959 includes.addRtlUstringH();
3960 includes.addRtlUstringHxx();
3961 includes.dump(o, nullptr, true);
3962 o << ("\n#if defined ANDROID || defined IOS //TODO\n"
3963 "#include <com/sun/star/lang/XInitialization.hpp>\n"
3964 "#include <osl/detail/component-defines.h>\n#endif\n\n"
3965 "#if defined LO_URE_CURRENT_ENV && defined LO_URE_CTOR_ENV_")
3966 << name_.replaceAll(".", "_dot_")
3967 << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_"
3968 << name_.replaceAll(".", "_dot_") << ") && defined LO_URE_CTOR_FUN_"
3969 << name_.replaceAll(".", "_dot_")
3970 << "\nextern \"C\" ::css::uno::XInterface * SAL_CALL LO_URE_CTOR_FUN_"
3971 << name_.replaceAll(".", "_dot_")
3972 << "(::css::uno::XComponentContext *, ::css::uno::Sequence< "
3973 "::css::uno::Any > const &);\n#endif\n";
3974 o << "\n";
3975 if (codemaker::cppumaker::dumpNamespaceOpen(o, name_, false)) {
3976 o << "\n";
3978 o << "\nclass " << cppName << " {\npublic:\n";
3979 inc();
3980 o << indent() << "static ::css::uno::Reference< "
3981 << scopedBaseName << " > "
3982 << codemaker::cpp::translateUnoToCppIdentifier(
3983 "get"_ostr, "method", codemaker::cpp::IdentifierTranslationMode::NonGlobal, &cppName)
3984 << ("(::css::uno::Reference<"
3985 " ::css::uno::XComponentContext > const & the_context)"
3986 " {\n");
3987 inc();
3988 o << indent() << "assert(the_context.is());\n" << indent()
3989 << "::css::uno::Reference< " << scopedBaseName
3990 << (" > instance;\n#if defined LO_URE_CURRENT_ENV && defined "
3991 "LO_URE_CTOR_ENV_")
3992 << name_.replaceAll(".", "_dot_")
3993 << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_"
3994 << name_.replaceAll(".", "_dot_")
3995 << ") && defined LO_URE_CTOR_FUN_"
3996 << name_.replaceAll(".", "_dot_") << "\n" << indent()
3997 << "instance = ::css::uno::Reference< " << scopedBaseName
3998 << (" >(::css::uno::Reference< ::css::uno::XInterface >("
3999 "static_cast< ::css::uno::XInterface * >((*"
4000 "LO_URE_CTOR_FUN_")
4001 << name_.replaceAll(".", "_dot_")
4002 << (")(the_context.get(), ::css::uno::Sequence<"
4003 " ::css::uno::Any >())), ::SAL_NO_ACQUIRE),"
4004 " ::css::uno::UNO_QUERY);\n#else\n")
4005 << indent() << ("the_context->getValueByName("
4006 "::rtl::OUString( \"/singletons/")
4007 << name_ << "\" )) >>= instance;\n#endif\n"
4008 << indent() << "if (!instance.is()) {\n";
4009 inc();
4010 o << indent()
4011 << ("throw ::css::uno::DeploymentException("
4012 "::rtl::OUString( \"component context"
4013 " fails to supply singleton ")
4014 << name_ << " of type " << baseName << "\" ), the_context);\n";
4015 dec();
4016 o << indent() << "}\n" << indent() << "return instance;\n";
4017 dec();
4018 o << indent() << "}\n\n";
4019 o << "private:\n";
4020 o << indent() << cppName << "(); // not implemented\n"
4021 << indent() << cppName << "(" << cppName << " &); // not implemented\n"
4022 << indent() << "~" << cppName << "(); // not implemented\n"
4023 << indent() << "void operator =(" << cppName << "); // not implemented\n";
4024 dec();
4025 o << "};\n\n";
4026 if (codemaker::cppumaker::dumpNamespaceClose(o, name_, false)) {
4027 o << "\n";
4029 o << "\n#endif // "<< headerDefine << "\n";
4034 void produce(
4035 OUString const & name, rtl::Reference< TypeManager > const & manager,
4036 codemaker::GeneratedTypeSet & generated, CppuOptions const & options)
4038 if (generated.contains(u2b(name))) {
4039 return;
4041 generated.add(u2b(name));
4042 if (!manager->foundAtPrimaryProvider(name)) {
4043 return;
4045 rtl::Reference< unoidl::Entity > ent;
4046 rtl::Reference< unoidl::MapCursor > cur;
4047 switch (manager->getSort(name, &ent, &cur)) {
4048 case codemaker::UnoType::Sort::Module: {
4049 OUString prefix;
4050 if (!name.isEmpty()) {
4051 prefix = name + ".";
4053 for (;;) {
4054 OUString mem;
4055 if (!cur->getNext(&mem).is()) {
4056 break;
4058 produce(prefix + mem, manager, generated, options);
4060 break;
4062 case codemaker::UnoType::Sort::Enum: {
4063 EnumType t(
4064 dynamic_cast< unoidl::EnumTypeEntity * >(ent.get()), name,
4065 manager);
4066 t.dump(options);
4067 t.dumpDependedTypes(generated, options);
4068 break;
4070 case codemaker::UnoType::Sort::PlainStruct: {
4071 PlainStructType t(
4072 dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get()),
4073 name, manager);
4074 t.dump(options);
4075 t.dumpDependedTypes(generated, options);
4076 break;
4078 case codemaker::UnoType::Sort::PolymorphicStructTemplate: {
4079 PolyStructType t(
4080 dynamic_cast< unoidl::PolymorphicStructTypeTemplateEntity * >(
4081 ent.get()),
4082 name, manager);
4083 t.dump(options);
4084 t.dumpDependedTypes(generated, options);
4085 break;
4087 case codemaker::UnoType::Sort::Exception: {
4088 ExceptionType t(
4089 dynamic_cast< unoidl::ExceptionTypeEntity * >(ent.get()), name,
4090 manager);
4091 t.dump(options);
4092 t.dumpDependedTypes(generated, options);
4093 break;
4095 case codemaker::UnoType::Sort::Interface: {
4096 InterfaceType t(
4097 dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get()), name,
4098 manager);
4099 t.dump(options);
4100 t.dumpDependedTypes(generated, options);
4101 break;
4103 case codemaker::UnoType::Sort::Typedef: {
4104 Typedef t(
4105 dynamic_cast< unoidl::TypedefEntity * >(ent.get()), name,
4106 manager);
4107 t.dump(options);
4108 t.dumpDependedTypes(generated, options);
4109 break;
4111 case codemaker::UnoType::Sort::ConstantGroup: {
4112 ConstantGroup t(
4113 dynamic_cast< unoidl::ConstantGroupEntity * >(ent.get()), name,
4114 manager);
4115 if (t.hasConstants()) {
4116 t.dump(options);
4118 break;
4120 case codemaker::UnoType::Sort::SingleInterfaceBasedService: {
4121 ServiceType t(
4122 dynamic_cast< unoidl::SingleInterfaceBasedServiceEntity * >(
4123 ent.get()),
4124 name, manager);
4125 t.dump(options);
4126 t.dumpDependedTypes(generated, options);
4127 break;
4129 case codemaker::UnoType::Sort::InterfaceBasedSingleton: {
4130 SingletonType t(
4131 dynamic_cast< unoidl::InterfaceBasedSingletonEntity * >(
4132 ent.get()),
4133 name, manager);
4134 t.dump(options);
4135 t.dumpDependedTypes(generated, options);
4136 break;
4138 case codemaker::UnoType::Sort::AccumulationBasedService:
4139 case codemaker::UnoType::Sort::ServiceBasedSingleton:
4140 break;
4141 default:
4142 throw CannotDumpException(
4143 "unexpected entity \"" + name + "\" in call to produce");
4147 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */