1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
22 #include <unordered_map>
31 #include <sal/log.hxx>
32 #include <osl/interlck.h>
33 #include <osl/mutex.hxx>
34 #include <rtl/ustring.hxx>
35 #include <osl/diagnose.h>
36 #include <typelib/typedescription.h>
38 #include <o3tl/string_view.hxx>
39 #include "typelib.hxx"
50 * The double member determines the alignment.
51 * Under OS2 and MS-Windows the Alignment is min( 8, sizeof( type ) ).
52 * The alignment of a structure is min( 8, sizeof( max basic type ) ), the greatest basic type
53 * determines the alignment.
67 // the value of the maximal alignment
68 const sal_Int32 nMaxAlignment
= static_cast<sal_Int32
>( reinterpret_cast<sal_Size
>(&reinterpret_cast<AlignSize_Impl
*>(16)->dDouble
) - 16);
70 static sal_Int32
adjustAlignment( sal_Int32 nRequestedAlignment
)
72 if( nRequestedAlignment
> nMaxAlignment
)
73 nRequestedAlignment
= nMaxAlignment
;
74 return nRequestedAlignment
;
78 * Calculate the new size of the structure.
80 static sal_Int32
newAlignedSize(
81 sal_Int32 OldSize
, sal_Int32 ElementSize
, sal_Int32 NeededAlignment
)
83 NeededAlignment
= adjustAlignment( NeededAlignment
);
84 return (OldSize
+ NeededAlignment
-1) / NeededAlignment
* NeededAlignment
+ ElementSize
;
87 static sal_Int32
getDescriptionSize( typelib_TypeClass eTypeClass
)
89 OSL_ASSERT( typelib_TypeClass_TYPEDEF
!= eTypeClass
);
92 // The reference is the description
93 // if the description is empty, then it must be filled with
94 // the new description
97 case typelib_TypeClass_SEQUENCE
:
98 nSize
= sal_Int32(sizeof( typelib_IndirectTypeDescription
));
101 case typelib_TypeClass_STRUCT
:
102 nSize
= sal_Int32(sizeof( typelib_StructTypeDescription
));
105 case typelib_TypeClass_EXCEPTION
:
106 nSize
= sal_Int32(sizeof( typelib_CompoundTypeDescription
));
109 case typelib_TypeClass_ENUM
:
110 nSize
= sal_Int32(sizeof( typelib_EnumTypeDescription
));
113 case typelib_TypeClass_INTERFACE
:
114 nSize
= sal_Int32(sizeof( typelib_InterfaceTypeDescription
));
117 case typelib_TypeClass_INTERFACE_METHOD
:
118 nSize
= sal_Int32(sizeof( typelib_InterfaceMethodTypeDescription
));
121 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
122 nSize
= sal_Int32(sizeof( typelib_InterfaceAttributeTypeDescription
));
126 nSize
= sal_Int32(sizeof( typelib_TypeDescription
));
135 bool operator()(const sal_Unicode
* const & s1
, const sal_Unicode
* const & s2
) const
136 { return 0 == rtl_ustr_compare( s1
, s2
); }
142 size_t operator()(const sal_Unicode
* const & s
) const
143 { return rtl_ustr_hashCode( s
); }
148 // Heavy hack, the const sal_Unicode * is hold by the typedescription reference
149 typedef std::unordered_map
< const sal_Unicode
*, typelib_TypeDescriptionReference
*,
150 hashStr_Impl
, equalStr_Impl
> WeakMap_Impl
;
152 typedef std::pair
< void *, typelib_typedescription_Callback
> CallbackEntry
;
153 typedef std::list
< CallbackEntry
> CallbackSet_Impl
;
154 typedef std::list
< typelib_TypeDescription
* > TypeDescriptionList_Impl
;
156 // # of cached elements
157 constexpr auto nCacheSize
= 256;
161 struct TypeDescriptor_Init_Impl
163 // all type description references
164 WeakMap_Impl maWeakMap
;
165 // all type description callbacks
166 CallbackSet_Impl maCallbacks
;
167 // A cache to hold descriptions
168 TypeDescriptionList_Impl maCache
;
169 // The mutex to guard all type library accesses
172 inline void callChain( typelib_TypeDescription
** ppRet
, rtl_uString
* pName
);
174 #if OSL_DEBUG_LEVEL > 0
175 // only for debugging
176 sal_Int32 nTypeDescriptionCount
= 0;
177 sal_Int32 nCompoundTypeDescriptionCount
= 0;
178 sal_Int32 nIndirectTypeDescriptionCount
= 0;
179 sal_Int32 nEnumTypeDescriptionCount
= 0;
180 sal_Int32 nInterfaceMethodTypeDescriptionCount
= 0;
181 sal_Int32 nInterfaceAttributeTypeDescriptionCount
= 0;
182 sal_Int32 nInterfaceTypeDescriptionCount
= 0;
183 sal_Int32 nTypeDescriptionReferenceCount
= 0;
186 TypeDescriptor_Init_Impl() = default;
188 ~TypeDescriptor_Init_Impl();
193 inline void TypeDescriptor_Init_Impl::callChain(
194 typelib_TypeDescription
** ppRet
, rtl_uString
* pName
)
196 assert(ppRet
!= nullptr);
197 assert(*ppRet
== nullptr);
198 for( const CallbackEntry
& rEntry
: maCallbacks
)
200 (*rEntry
.second
)( rEntry
.first
, ppRet
, pName
);
207 TypeDescriptor_Init_Impl::~TypeDescriptor_Init_Impl()
209 for( typelib_TypeDescription
* pItem
: maCache
)
211 typelib_typedescription_release( pItem
);
215 std::vector
< typelib_TypeDescriptionReference
* > ppTDR
;
216 ppTDR
.reserve( maWeakMap
.size() );
218 // save all weak references
219 for( const auto& rEntry
: maWeakMap
)
221 ppTDR
.push_back( rEntry
.second
);
222 typelib_typedescriptionreference_acquire( ppTDR
.back() );
225 for( typelib_TypeDescriptionReference
* pTDR
: ppTDR
)
227 OSL_ASSERT( pTDR
->nRefCount
> pTDR
->nStaticRefCount
);
228 pTDR
->nRefCount
-= pTDR
->nStaticRefCount
;
230 if( pTDR
->pType
&& !pTDR
->pType
->bOnDemand
)
232 pTDR
->pType
->bOnDemand
= true;
233 typelib_typedescription_release( pTDR
->pType
);
235 typelib_typedescriptionreference_release( pTDR
);
238 #if defined SAL_LOG_INFO
239 for( const auto& rEntry
: maWeakMap
)
241 typelib_TypeDescriptionReference
* pTDR
= rEntry
.second
;
244 OString
aTypeName( OUStringToOString( OUString::unacquired(&pTDR
->pTypeName
), RTL_TEXTENCODING_ASCII_US
) );
245 SAL_INFO("cppu.typelib", "remaining type: " << aTypeName
<< "; ref count = " << pTDR
->nRefCount
);
249 SAL_INFO("cppu.typelib", "remaining null type entry!?");
254 #if OSL_DEBUG_LEVEL > 0
255 SAL_INFO_IF( nTypeDescriptionCount
, "cppu.typelib", "nTypeDescriptionCount is not zero" );
256 SAL_INFO_IF( nCompoundTypeDescriptionCount
, "cppu.typelib", "nCompoundTypeDescriptionCount is not zero" );
257 SAL_INFO_IF( nIndirectTypeDescriptionCount
, "cppu.typelib", "nIndirectTypeDescriptionCount is not zero" );
258 SAL_INFO_IF( nEnumTypeDescriptionCount
, "cppu.typelib", "nEnumTypeDescriptionCount is not zero" );
259 SAL_INFO_IF( nInterfaceMethodTypeDescriptionCount
, "cppu.typelib", "nInterfaceMethodTypeDescriptionCount is not zero" );
260 SAL_INFO_IF( nInterfaceAttributeTypeDescriptionCount
, "cppu.typelib", "nInterfaceAttributeTypeDescriptionCount is not zero" );
261 SAL_INFO_IF( nInterfaceTypeDescriptionCount
, "cppu.typelib", "nInterfaceTypeDescriptionCount is not zero" );
262 SAL_INFO_IF( nTypeDescriptionReferenceCount
, "cppu.typelib", "nTypeDescriptionReferenceCount is not zero" );
265 SAL_INFO_IF( !maCallbacks
.empty(), "cppu.typelib", "pCallbacks is not NULL or empty" );
269 TypeDescriptor_Init_Impl
& Init()
271 static TypeDescriptor_Init_Impl SINGLETON
;
276 extern "C" void SAL_CALL
typelib_typedescription_registerCallback(
277 void * pContext
, typelib_typedescription_Callback pCallback
) noexcept
279 // todo mt safe: guard is no solution, can not acquire while calling callback!
280 TypeDescriptor_Init_Impl
&rInit
= Init();
281 // OslGuard aGuard( rInit.getMutex() );
282 rInit
.maCallbacks
.push_back( CallbackEntry( pContext
, pCallback
) );
286 extern "C" void SAL_CALL
typelib_typedescription_revokeCallback(
287 void * pContext
, typelib_typedescription_Callback pCallback
) noexcept
289 TypeDescriptor_Init_Impl
&rInit
= Init();
291 // todo mt safe: guard is no solution, can not acquire while calling callback!
292 // OslGuard aGuard( rInit.getMutex() );
293 CallbackEntry
aEntry( pContext
, pCallback
);
294 std::erase(rInit
.maCallbacks
, aEntry
);
298 static void typelib_typedescription_initTables(
299 typelib_TypeDescription
* pTD
)
301 typelib_InterfaceTypeDescription
* pITD
= reinterpret_cast<typelib_InterfaceTypeDescription
*>(pTD
);
303 std::vector
<bool> aReadWriteAttributes(pITD
->nAllMembers
);
304 for ( sal_Int32 i
= pITD
->nAllMembers
; i
--; )
306 aReadWriteAttributes
[i
] = false;
307 if( typelib_TypeClass_INTERFACE_ATTRIBUTE
== pITD
->ppAllMembers
[i
]->eTypeClass
)
309 typelib_TypeDescription
* pM
= nullptr;
310 TYPELIB_DANGER_GET( &pM
, pITD
->ppAllMembers
[i
] );
314 aReadWriteAttributes
[i
] = !reinterpret_cast<typelib_InterfaceAttributeTypeDescription
*>(pM
)->bReadOnly
;
315 TYPELIB_DANGER_RELEASE( pM
);
319 SAL_INFO( "cppu.typelib", "cannot get attribute type description: " << pITD
->ppAllMembers
[i
]->pTypeName
);
324 MutexGuard
aGuard( Init().maMutex
);
328 // create the index table from member to function table
329 pITD
->pMapMemberIndexToFunctionIndex
= new sal_Int32
[ pITD
->nAllMembers
];
330 sal_Int32 nAdditionalOffset
= 0; // +1 for read/write attributes
332 for( i
= 0; i
< pITD
->nAllMembers
; i
++ )
334 // index to the get method of the attribute
335 pITD
->pMapMemberIndexToFunctionIndex
[i
] = i
+ nAdditionalOffset
;
336 // extra offset if it is a read/write attribute?
337 if (aReadWriteAttributes
[i
])
339 // a read/write attribute
344 // create the index table from function to member table
345 pITD
->pMapFunctionIndexToMemberIndex
= new sal_Int32
[ pITD
->nAllMembers
+ nAdditionalOffset
];
346 nAdditionalOffset
= 0; // +1 for read/write attributes
347 for( i
= 0; i
< pITD
->nAllMembers
; i
++ )
349 // index to the get method of the attribute
350 pITD
->pMapFunctionIndexToMemberIndex
[i
+ nAdditionalOffset
] = i
;
351 // extra offset if it is a read/write attribute?
352 if (aReadWriteAttributes
[i
])
354 // a read/write attribute
355 pITD
->pMapFunctionIndexToMemberIndex
[i
+ ++nAdditionalOffset
] = i
;
358 // must be the last action after all initialization is done
359 pITD
->nMapFunctionIndexToMemberIndex
= pITD
->nAllMembers
+ nAdditionalOffset
;
360 pTD
->bComplete
= true;
365 template<typename T
> T
* allocTypeDescription() {
366 return reinterpret_cast<T
*>(new char[sizeof (T
)]);
369 void freeTypeDescription(typelib_TypeDescription
const * desc
) {
370 delete[] reinterpret_cast<char const *>(desc
);
373 // In some situations (notably typelib_typedescription_newInterfaceMethod and
374 // typelib_typedescription_newInterfaceAttribute), only the members nMembers,
375 // ppMembers, nAllMembers, and ppAllMembers of an incomplete interface type
376 // description are necessary, but not the additional
377 // pMapMemberIndexToFunctionIndex, nMapFunctionIndexToMemberIndex, and
378 // pMapFunctionIndexToMemberIndex (which are computed by
379 // typelib_typedescription_initTables). Furthermore, in those situations, it
380 // might be illegal to compute those tables, as the creation of the interface
381 // member type descriptions would recursively require a complete interface type
382 // description. The parameter initTables controls whether or not to call
383 // typelib_typedescription_initTables in those situations.
384 bool complete(typelib_TypeDescription
** ppTypeDescr
, bool initTables
) {
385 if ((*ppTypeDescr
)->bComplete
)
388 OSL_ASSERT( (typelib_TypeClass_STRUCT
== (*ppTypeDescr
)->eTypeClass
||
389 typelib_TypeClass_EXCEPTION
== (*ppTypeDescr
)->eTypeClass
||
390 typelib_TypeClass_ENUM
== (*ppTypeDescr
)->eTypeClass
||
391 typelib_TypeClass_INTERFACE
== (*ppTypeDescr
)->eTypeClass
) &&
392 !TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( (*ppTypeDescr
)->eTypeClass
) );
394 if (typelib_TypeClass_INTERFACE
== (*ppTypeDescr
)->eTypeClass
&&
395 reinterpret_cast<typelib_InterfaceTypeDescription
*>(*ppTypeDescr
)->ppAllMembers
)
398 typelib_typedescription_initTables( *ppTypeDescr
);
403 typelib_TypeDescription
* pTD
= nullptr;
404 // on demand access of complete td
405 TypeDescriptor_Init_Impl
&rInit
= Init();
406 rInit
.callChain( &pTD
, (*ppTypeDescr
)->pTypeName
);
409 if (typelib_TypeClass_TYPEDEF
== pTD
->eTypeClass
)
411 typelib_typedescriptionreference_getDescription(
412 &pTD
, reinterpret_cast<typelib_IndirectTypeDescription
*>(pTD
)->pType
);
418 OSL_ASSERT( typelib_TypeClass_TYPEDEF
!= pTD
->eTypeClass
);
419 // typedescription found
421 pTD
->bOnDemand
= true;
423 if (pTD
->eTypeClass
== typelib_TypeClass_INTERFACE
424 && !pTD
->bComplete
&& initTables
)
426 // mandatory info from callback chain
427 OSL_ASSERT( reinterpret_cast<typelib_InterfaceTypeDescription
*>(pTD
)->ppAllMembers
);
428 // complete except of tables init
429 typelib_typedescription_initTables( pTD
);
430 pTD
->bComplete
= true;
433 // The type description is hold by the reference until
434 // on demand is activated.
435 ::typelib_typedescription_register( &pTD
); // replaces incomplete one
436 OSL_ASSERT( pTD
== *ppTypeDescr
); // has to merge into existing one
438 // insert into the cache
439 MutexGuard
aGuard( rInit
.maMutex
);
440 if( rInit
.maCache
.size() >= nCacheSize
)
442 typelib_typedescription_release( rInit
.maCache
.front() );
443 rInit
.maCache
.pop_front();
445 // descriptions in the cache must be acquired!
446 typelib_typedescription_acquire( pTD
);
447 rInit
.maCache
.push_back( pTD
);
451 || (pTD
->eTypeClass
== typelib_TypeClass_INTERFACE
454 ::typelib_typedescription_release( *ppTypeDescr
);
461 "type cannot be completed: " << OUString::unacquired(&(*ppTypeDescr
)->pTypeName
));
470 extern "C" void typelib_typedescription_newEmpty(
471 typelib_TypeDescription
** ppRet
,
472 typelib_TypeClass eTypeClass
, rtl_uString
* pTypeName
) noexcept
476 typelib_typedescription_release( *ppRet
);
480 OSL_ASSERT( typelib_TypeClass_TYPEDEF
!= eTypeClass
);
482 typelib_TypeDescription
* pRet
;
485 case typelib_TypeClass_SEQUENCE
:
487 auto pTmp
= allocTypeDescription
<typelib_IndirectTypeDescription
>();
489 #if OSL_DEBUG_LEVEL > 0
490 osl_atomic_increment( &Init().nIndirectTypeDescriptionCount
);
492 pTmp
->pType
= nullptr;
493 // coverity[leaked_storage] - this is on purpose
497 case typelib_TypeClass_STRUCT
:
499 // FEATURE_EMPTYCLASS
500 auto pTmp
= allocTypeDescription
<typelib_StructTypeDescription
>();
501 pRet
= &pTmp
->aBase
.aBase
;
502 #if OSL_DEBUG_LEVEL > 0
503 osl_atomic_increment( &Init().nCompoundTypeDescriptionCount
);
505 pTmp
->aBase
.pBaseTypeDescription
= nullptr;
506 pTmp
->aBase
.nMembers
= 0;
507 pTmp
->aBase
.pMemberOffsets
= nullptr;
508 pTmp
->aBase
.ppTypeRefs
= nullptr;
509 pTmp
->aBase
.ppMemberNames
= nullptr;
510 pTmp
->pParameterizedTypes
= nullptr;
511 // coverity[leaked_storage] - this is on purpose
515 case typelib_TypeClass_EXCEPTION
:
517 // FEATURE_EMPTYCLASS
518 auto pTmp
= allocTypeDescription
<typelib_CompoundTypeDescription
>();
520 #if OSL_DEBUG_LEVEL > 0
521 osl_atomic_increment( &Init().nCompoundTypeDescriptionCount
);
523 pTmp
->pBaseTypeDescription
= nullptr;
525 pTmp
->pMemberOffsets
= nullptr;
526 pTmp
->ppTypeRefs
= nullptr;
527 pTmp
->ppMemberNames
= nullptr;
528 // coverity[leaked_storage] - this is on purpose
532 case typelib_TypeClass_ENUM
:
534 auto pTmp
= allocTypeDescription
<typelib_EnumTypeDescription
>();
536 #if OSL_DEBUG_LEVEL > 0
537 osl_atomic_increment( &Init().nEnumTypeDescriptionCount
);
539 pTmp
->nDefaultEnumValue
= 0;
540 pTmp
->nEnumValues
= 0;
541 pTmp
->ppEnumNames
= nullptr;
542 pTmp
->pEnumValues
= nullptr;
543 // coverity[leaked_storage] - this is on purpose
547 case typelib_TypeClass_INTERFACE
:
549 auto pTmp
= allocTypeDescription
<
550 typelib_InterfaceTypeDescription
>();
552 #if OSL_DEBUG_LEVEL > 0
553 osl_atomic_increment( &Init().nInterfaceTypeDescriptionCount
);
555 pTmp
->pBaseTypeDescription
= nullptr;
557 pTmp
->ppMembers
= nullptr;
558 pTmp
->nAllMembers
= 0;
559 pTmp
->ppAllMembers
= nullptr;
560 pTmp
->nMapFunctionIndexToMemberIndex
= 0;
561 pTmp
->pMapFunctionIndexToMemberIndex
= nullptr;
562 pTmp
->pMapMemberIndexToFunctionIndex
= nullptr;
563 pTmp
->nBaseTypes
= 0;
564 pTmp
->ppBaseTypes
= nullptr;
565 // coverity[leaked_storage] - this is on purpose
569 case typelib_TypeClass_INTERFACE_METHOD
:
571 auto pTmp
= allocTypeDescription
<
572 typelib_InterfaceMethodTypeDescription
>();
573 pRet
= &pTmp
->aBase
.aBase
;
574 #if OSL_DEBUG_LEVEL > 0
575 osl_atomic_increment( &Init().nInterfaceMethodTypeDescriptionCount
);
577 pTmp
->aBase
.pMemberName
= nullptr;
578 pTmp
->pReturnTypeRef
= nullptr;
580 pTmp
->pParams
= nullptr;
581 pTmp
->nExceptions
= 0;
582 pTmp
->ppExceptions
= nullptr;
583 pTmp
->pInterface
= nullptr;
584 pTmp
->pBaseRef
= nullptr;
586 // coverity[leaked_storage] - this is on purpose
590 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
592 auto * pTmp
= allocTypeDescription
<
593 typelib_InterfaceAttributeTypeDescription
>();
594 pRet
= &pTmp
->aBase
.aBase
;
595 #if OSL_DEBUG_LEVEL > 0
596 osl_atomic_increment( &Init().nInterfaceAttributeTypeDescriptionCount
);
598 pTmp
->aBase
.pMemberName
= nullptr;
599 pTmp
->pAttributeTypeRef
= nullptr;
600 pTmp
->pInterface
= nullptr;
601 pTmp
->pBaseRef
= nullptr;
603 pTmp
->nGetExceptions
= 0;
604 pTmp
->ppGetExceptions
= nullptr;
605 pTmp
->nSetExceptions
= 0;
606 pTmp
->ppSetExceptions
= nullptr;
607 // coverity[leaked_storage] - this is on purpose
613 pRet
= allocTypeDescription
<typelib_TypeDescription
>();
614 #if OSL_DEBUG_LEVEL > 0
615 osl_atomic_increment( &Init().nTypeDescriptionCount
);
620 pRet
->nRefCount
= 1; // reference count is initially 1
621 pRet
->nStaticRefCount
= 0;
622 pRet
->eTypeClass
= eTypeClass
;
623 pRet
->pUniqueIdentifier
= nullptr;
624 pRet
->pReserved
= nullptr;
625 pRet
->pTypeName
= pTypeName
;
626 rtl_uString_acquire( pRet
->pTypeName
);
628 pRet
->bComplete
= true;
630 pRet
->nAlignment
= 0;
631 pRet
->pWeakRef
= nullptr;
632 pRet
->bOnDemand
= false;
639 void newTypeDescription(
640 typelib_TypeDescription
** ppRet
, typelib_TypeClass eTypeClass
,
641 rtl_uString
* pTypeName
, typelib_TypeDescriptionReference
* pType
,
642 sal_Int32 nMembers
, typelib_CompoundMember_Init
* pCompoundMembers
,
643 typelib_StructMember_Init
* pStructMembers
)
646 (pCompoundMembers
== nullptr || pStructMembers
== nullptr)
647 && (pStructMembers
== nullptr || eTypeClass
== typelib_TypeClass_STRUCT
));
648 if (typelib_TypeClass_TYPEDEF
== eTypeClass
)
650 SAL_WARN("cppu.typelib", "unexpected typedef!" );
651 typelib_typedescriptionreference_getDescription( ppRet
, pType
);
655 typelib_typedescription_newEmpty( ppRet
, eTypeClass
, pTypeName
);
659 case typelib_TypeClass_SEQUENCE
:
661 OSL_ASSERT( nMembers
== 0 );
662 typelib_typedescriptionreference_acquire( pType
);
663 reinterpret_cast<typelib_IndirectTypeDescription
*>(*ppRet
)->pType
= pType
;
667 case typelib_TypeClass_EXCEPTION
:
668 case typelib_TypeClass_STRUCT
:
670 // FEATURE_EMPTYCLASS
671 typelib_CompoundTypeDescription
* pTmp
= reinterpret_cast<typelib_CompoundTypeDescription
*>(*ppRet
);
673 sal_Int32 nOffset
= 0;
676 typelib_typedescriptionreference_getDescription(
677 reinterpret_cast<typelib_TypeDescription
**>(&pTmp
->pBaseTypeDescription
), pType
);
678 nOffset
= pTmp
->pBaseTypeDescription
->aBase
.nSize
;
679 OSL_ENSURE( newAlignedSize( 0, pTmp
->pBaseTypeDescription
->aBase
.nSize
, pTmp
->pBaseTypeDescription
->aBase
.nAlignment
) == pTmp
->pBaseTypeDescription
->aBase
.nSize
, "### unexpected offset!" );
683 pTmp
->nMembers
= nMembers
;
684 pTmp
->pMemberOffsets
= new sal_Int32
[ nMembers
];
685 pTmp
->ppTypeRefs
= new typelib_TypeDescriptionReference
*[ nMembers
];
686 pTmp
->ppMemberNames
= new rtl_uString
*[ nMembers
];
687 bool polymorphic
= eTypeClass
== typelib_TypeClass_STRUCT
688 && OUString::unacquired(&pTypeName
).indexOf('<') >= 0;
689 assert(!polymorphic
|| pStructMembers
!= nullptr);
691 reinterpret_cast< typelib_StructTypeDescription
* >(pTmp
)->
692 pParameterizedTypes
= new sal_Bool
[nMembers
];
694 for( sal_Int32 i
= 0 ; i
< nMembers
; i
++ )
696 // read the type and member names
697 pTmp
->ppTypeRefs
[i
] = nullptr;
698 if (pCompoundMembers
!= nullptr) {
699 typelib_typedescriptionreference_new(
700 pTmp
->ppTypeRefs
+i
, pCompoundMembers
[i
].eTypeClass
,
701 pCompoundMembers
[i
].pTypeName
);
702 pTmp
->ppMemberNames
[i
]
703 = pCompoundMembers
[i
].pMemberName
;
704 rtl_uString_acquire( pTmp
->ppMemberNames
[i
] );
706 typelib_typedescriptionreference_new(
708 pStructMembers
[i
].aBase
.eTypeClass
,
709 pStructMembers
[i
].aBase
.pTypeName
);
710 pTmp
->ppMemberNames
[i
]
711 = pStructMembers
[i
].aBase
.pMemberName
;
712 rtl_uString_acquire(pTmp
->ppMemberNames
[i
]);
714 assert(pTmp
->ppTypeRefs
[i
]);
718 if (pTmp
->ppTypeRefs
[i
]->eTypeClass
==
719 typelib_TypeClass_SEQUENCE
)
721 // Take care of recursion like
722 // struct S { sequence<S> x; };
723 size
= sizeof(void *);
724 alignment
= adjustAlignment(size
);
726 typelib_TypeDescription
* pTD
= nullptr;
727 TYPELIB_DANGER_GET( &pTD
, pTmp
->ppTypeRefs
[i
] );
728 OSL_ENSURE( pTD
->nSize
, "### void member?" );
730 alignment
= pTD
->nAlignment
;
731 TYPELIB_DANGER_RELEASE( pTD
);
733 nOffset
= newAlignedSize( nOffset
, size
, alignment
);
734 pTmp
->pMemberOffsets
[i
] = nOffset
- size
;
737 reinterpret_cast< typelib_StructTypeDescription
* >(
738 pTmp
)->pParameterizedTypes
[i
]
739 = pStructMembers
[i
].bParameterizedType
;
750 if( !TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( eTypeClass
) )
751 (*ppRet
)->pWeakRef
= reinterpret_cast<typelib_TypeDescriptionReference
*>(*ppRet
);
752 if( eTypeClass
!= typelib_TypeClass_VOID
)
754 // sizeof(void) not allowed
755 (*ppRet
)->nSize
= typelib_typedescription_getAlignedUnoSize( (*ppRet
), 0, (*ppRet
)->nAlignment
);
756 (*ppRet
)->nAlignment
= adjustAlignment( (*ppRet
)->nAlignment
);
762 extern "C" void SAL_CALL
typelib_typedescription_new(
763 typelib_TypeDescription
** ppRet
,
764 typelib_TypeClass eTypeClass
,
765 rtl_uString
* pTypeName
,
766 typelib_TypeDescriptionReference
* pType
,
768 typelib_CompoundMember_Init
* pMembers
) noexcept
771 ppRet
, eTypeClass
, pTypeName
, pType
, nMembers
, pMembers
, nullptr);
774 extern "C" void SAL_CALL
typelib_typedescription_newStruct(
775 typelib_TypeDescription
** ppRet
,
776 rtl_uString
* pTypeName
,
777 typelib_TypeDescriptionReference
* pType
,
779 typelib_StructMember_Init
* pMembers
) noexcept
782 ppRet
, typelib_TypeClass_STRUCT
, pTypeName
, pType
, nMembers
, nullptr,
787 extern "C" void SAL_CALL
typelib_typedescription_newEnum(
788 typelib_TypeDescription
** ppRet
,
789 rtl_uString
* pTypeName
,
790 sal_Int32 nDefaultValue
,
791 sal_Int32 nEnumValues
,
792 rtl_uString
** ppEnumNames
,
793 sal_Int32
* pEnumValues
) noexcept
795 typelib_typedescription_newEmpty( ppRet
, typelib_TypeClass_ENUM
, pTypeName
);
796 typelib_EnumTypeDescription
* pEnum
= reinterpret_cast<typelib_EnumTypeDescription
*>(*ppRet
);
798 pEnum
->nDefaultEnumValue
= nDefaultValue
;
799 pEnum
->nEnumValues
= nEnumValues
;
800 pEnum
->ppEnumNames
= new rtl_uString
* [ nEnumValues
];
801 for ( sal_Int32 nPos
= nEnumValues
; nPos
--; )
803 pEnum
->ppEnumNames
[nPos
] = ppEnumNames
[nPos
];
804 rtl_uString_acquire( pEnum
->ppEnumNames
[nPos
] );
806 pEnum
->pEnumValues
= new sal_Int32
[ nEnumValues
];
807 ::memcpy( pEnum
->pEnumValues
, pEnumValues
, nEnumValues
* sizeof(sal_Int32
) );
809 static_assert(!TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK(typelib_TypeClass_ENUM
));
810 (*ppRet
)->pWeakRef
= reinterpret_cast<typelib_TypeDescriptionReference
*>(*ppRet
);
811 // sizeof(void) not allowed
812 (*ppRet
)->nSize
= typelib_typedescription_getAlignedUnoSize( (*ppRet
), 0, (*ppRet
)->nAlignment
);
813 (*ppRet
)->nAlignment
= adjustAlignment( (*ppRet
)->nAlignment
);
817 extern "C" void SAL_CALL
typelib_typedescription_newInterface(
818 typelib_InterfaceTypeDescription
** ppRet
,
819 rtl_uString
* pTypeName
,
820 SAL_UNUSED_PARAMETER sal_uInt32
, SAL_UNUSED_PARAMETER sal_uInt16
,
821 SAL_UNUSED_PARAMETER sal_uInt16
, SAL_UNUSED_PARAMETER sal_uInt32
,
822 SAL_UNUSED_PARAMETER sal_uInt32
,
823 typelib_TypeDescriptionReference
* pBaseInterface
,
825 typelib_TypeDescriptionReference
** ppMembers
) noexcept
827 // coverity[callee_ptr_arith] - not a bug
828 typelib_typedescription_newMIInterface(
829 ppRet
, pTypeName
, 0, 0, 0, 0, 0, pBaseInterface
== nullptr ? 0 : 1,
830 &pBaseInterface
, nMembers
, ppMembers
);
838 sal_Int32 memberOffset
;
839 sal_Int32 directBaseIndex
;
840 sal_Int32 directBaseMemberOffset
;
841 typelib_InterfaceTypeDescription
const * base
;
844 typedef std::vector
< Entry
> List
;
846 explicit BaseList(typelib_InterfaceTypeDescription
const * desc
);
848 List
const & getList() const { return list
; }
850 sal_Int32
getBaseMembers() const { return members
; }
853 typedef std::set
< OUString
> Set
;
857 sal_Int32 directBaseIndex
, Set
& directBaseSet
,
858 sal_Int32
* directBaseMembers
,
859 typelib_InterfaceTypeDescription
const * desc
);
865 BaseList::BaseList(typelib_InterfaceTypeDescription
const * desc
)
869 for (sal_Int32 i
= 0; i
< desc
->nBaseTypes
; ++i
) {
871 sal_Int32 directBaseMembers
= 0;
872 calculate(allSet
, i
, directBaseSet
, &directBaseMembers
, desc
->ppBaseTypes
[i
]);
876 void BaseList::calculate(
878 sal_Int32 directBaseIndex
, Set
& directBaseSet
,
879 sal_Int32
* directBaseMembers
,
880 typelib_InterfaceTypeDescription
const * desc
)
882 for (sal_Int32 i
= 0; i
< desc
->nBaseTypes
; ++i
) {
884 directBaseIndex
, directBaseSet
, directBaseMembers
,
885 desc
->ppBaseTypes
[i
]);
887 if (allSet
.insert(desc
->aBase
.pTypeName
).second
) {
889 e
.memberOffset
= members
;
890 e
.directBaseIndex
= directBaseIndex
;
891 e
.directBaseMemberOffset
= *directBaseMembers
;
894 OSL_ASSERT(desc
->ppAllMembers
!= nullptr);
895 members
+= desc
->nMembers
;
897 if (directBaseSet
.insert(desc
->aBase
.pTypeName
).second
) {
898 OSL_ASSERT(desc
->ppAllMembers
!= nullptr);
899 *directBaseMembers
+= desc
->nMembers
;
905 extern "C" void SAL_CALL
typelib_typedescription_newMIInterface(
906 typelib_InterfaceTypeDescription
** ppRet
,
907 rtl_uString
* pTypeName
,
908 SAL_UNUSED_PARAMETER sal_uInt32
, SAL_UNUSED_PARAMETER sal_uInt16
,
909 SAL_UNUSED_PARAMETER sal_uInt16
, SAL_UNUSED_PARAMETER sal_uInt32
,
910 SAL_UNUSED_PARAMETER sal_uInt32
,
911 sal_Int32 nBaseInterfaces
,
912 typelib_TypeDescriptionReference
** ppBaseInterfaces
,
914 typelib_TypeDescriptionReference
** ppMembers
) noexcept
916 if (*ppRet
!= nullptr) {
917 typelib_typedescription_release(&(*ppRet
)->aBase
);
921 typelib_InterfaceTypeDescription
* pITD
= nullptr;
922 typelib_typedescription_newEmpty(
923 reinterpret_cast<typelib_TypeDescription
**>(&pITD
), typelib_TypeClass_INTERFACE
, pTypeName
);
925 pITD
->nBaseTypes
= nBaseInterfaces
;
926 pITD
->ppBaseTypes
= new typelib_InterfaceTypeDescription
*[nBaseInterfaces
];
927 for (sal_Int32 i
= 0; i
< nBaseInterfaces
; ++i
) {
928 pITD
->ppBaseTypes
[i
] = nullptr;
929 typelib_typedescriptionreference_getDescription(
930 reinterpret_cast< typelib_TypeDescription
** >(
931 &pITD
->ppBaseTypes
[i
]),
932 ppBaseInterfaces
[i
]);
933 if (pITD
->ppBaseTypes
[i
] == nullptr
935 reinterpret_cast< typelib_TypeDescription
** >(
936 &pITD
->ppBaseTypes
[i
]),
942 OSL_ASSERT(pITD
->ppBaseTypes
[i
] != nullptr);
944 if (nBaseInterfaces
> 0) {
945 pITD
->pBaseTypeDescription
= pITD
->ppBaseTypes
[0];
948 pITD
->aUik
.m_Data1
= 0;
949 pITD
->aUik
.m_Data2
= 0;
950 pITD
->aUik
.m_Data3
= 0;
951 pITD
->aUik
.m_Data4
= 0;
952 pITD
->aUik
.m_Data5
= 0;
954 BaseList
aBaseList(pITD
);
955 pITD
->nAllMembers
= nMembers
+ aBaseList
.getBaseMembers();
956 pITD
->nMembers
= nMembers
;
958 if( pITD
->nAllMembers
)
960 // at minimum one member exist, allocate the memory
961 pITD
->ppAllMembers
= new typelib_TypeDescriptionReference
*[ pITD
->nAllMembers
];
964 BaseList::List
const & rList
= aBaseList
.getList();
965 for (const auto& rEntry
: rList
)
967 typelib_InterfaceTypeDescription
const * pBase
= rEntry
.base
;
968 typelib_InterfaceTypeDescription
const * pDirectBase
969 = pITD
->ppBaseTypes
[rEntry
.directBaseIndex
];
970 OSL_ASSERT(pBase
->ppAllMembers
!= nullptr);
971 for (sal_Int32 j
= 0; j
< pBase
->nMembers
; ++j
) {
972 typelib_TypeDescriptionReference
const * pDirectBaseMember
973 = pDirectBase
->ppAllMembers
[rEntry
.directBaseMemberOffset
+ j
];
974 OUString aName
= OUString::unacquired(&pDirectBaseMember
->pTypeName
) +
976 OUString::number(rEntry
.directBaseIndex
) +
978 OUString::number(rEntry
.memberOffset
+ j
) +
980 OUString::unacquired(&pITD
->aBase
.pTypeName
);
981 typelib_TypeDescriptionReference
* pDerivedMember
= nullptr;
982 typelib_typedescriptionreference_new(
983 &pDerivedMember
, pDirectBaseMember
->eTypeClass
,
985 pITD
->ppAllMembers
[n
++] = pDerivedMember
;
991 pITD
->ppMembers
= pITD
->ppAllMembers
+ aBaseList
.getBaseMembers();
995 for( sal_Int32 i
= 0; i
< nMembers
; i
++ )
997 typelib_typedescriptionreference_acquire( ppMembers
[i
] );
998 pITD
->ppAllMembers
[n
++] = ppMembers
[i
];
1002 typelib_TypeDescription
* pTmp
= &pITD
->aBase
;
1003 static_assert( !TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( typelib_TypeClass_INTERFACE
) );
1004 pTmp
->pWeakRef
= reinterpret_cast<typelib_TypeDescriptionReference
*>(pTmp
);
1005 pTmp
->nSize
= typelib_typedescription_getAlignedUnoSize( pTmp
, 0, pTmp
->nAlignment
);
1006 pTmp
->nAlignment
= adjustAlignment( pTmp
->nAlignment
);
1007 pTmp
->bComplete
= false;
1015 typelib_TypeDescriptionReference
** copyExceptions(
1016 sal_Int32 count
, rtl_uString
** typeNames
)
1018 OSL_ASSERT(count
>= 0);
1022 typelib_TypeDescriptionReference
** p
1023 = new typelib_TypeDescriptionReference
*[count
];
1024 for (sal_Int32 i
= 0; i
< count
; ++i
) {
1026 typelib_typedescriptionreference_new(
1027 p
+ i
, typelib_TypeClass_EXCEPTION
, typeNames
[i
]);
1034 extern "C" void SAL_CALL
typelib_typedescription_newInterfaceMethod(
1035 typelib_InterfaceMethodTypeDescription
** ppRet
,
1036 sal_Int32 nAbsolutePosition
,
1038 rtl_uString
* pTypeName
,
1039 typelib_TypeClass eReturnTypeClass
,
1040 rtl_uString
* pReturnTypeName
,
1042 typelib_Parameter_Init
* pParams
,
1043 sal_Int32 nExceptions
,
1044 rtl_uString
** ppExceptionNames
) noexcept
1046 if (*ppRet
!= nullptr) {
1047 typelib_typedescription_release(&(*ppRet
)->aBase
.aBase
);
1050 sal_Int32 nOffset
= rtl_ustr_lastIndexOfChar_WithLength(
1051 pTypeName
->buffer
, pTypeName
->length
, ':');
1052 if (nOffset
<= 0 || pTypeName
->buffer
[nOffset
- 1] != ':') {
1053 OSL_FAIL("Bad interface method type name");
1056 OUString
aInterfaceTypeName(pTypeName
->buffer
, nOffset
- 1);
1057 typelib_InterfaceTypeDescription
* pInterface
= nullptr;
1058 typelib_typedescription_getByName(
1059 reinterpret_cast< typelib_TypeDescription
** >(&pInterface
),
1060 aInterfaceTypeName
.pData
);
1061 if (pInterface
== nullptr
1062 || pInterface
->aBase
.eTypeClass
!= typelib_TypeClass_INTERFACE
1064 reinterpret_cast< typelib_TypeDescription
** >(&pInterface
), false))
1066 OSL_FAIL("No interface corresponding to interface method");
1070 typelib_typedescription_newEmpty(
1071 reinterpret_cast<typelib_TypeDescription
**>(ppRet
), typelib_TypeClass_INTERFACE_METHOD
, pTypeName
);
1073 rtl_uString_newFromStr_WithLength( &(*ppRet
)->aBase
.pMemberName
,
1074 pTypeName
->buffer
+ nOffset
+1,
1075 pTypeName
->length
- nOffset
-1 );
1076 (*ppRet
)->aBase
.nPosition
= nAbsolutePosition
;
1077 (*ppRet
)->bOneWay
= bOneWay
;
1078 typelib_typedescriptionreference_new( &(*ppRet
)->pReturnTypeRef
, eReturnTypeClass
, pReturnTypeName
);
1079 (*ppRet
)->nParams
= nParams
;
1082 (*ppRet
)->pParams
= new typelib_MethodParameter
[ nParams
];
1084 for( sal_Int32 i
= 0; i
< nParams
; i
++ )
1086 // get the name of the parameter
1087 (*ppRet
)->pParams
[ i
].pName
= pParams
[i
].pParamName
;
1088 rtl_uString_acquire( (*ppRet
)->pParams
[ i
].pName
);
1089 (*ppRet
)->pParams
[ i
].pTypeRef
= nullptr;
1090 // get the type name of the parameter and create the weak reference
1091 typelib_typedescriptionreference_new(
1092 &(*ppRet
)->pParams
[ i
].pTypeRef
, pParams
[i
].eTypeClass
, pParams
[i
].pTypeName
);
1093 (*ppRet
)->pParams
[ i
].bIn
= pParams
[i
].bIn
;
1094 (*ppRet
)->pParams
[ i
].bOut
= pParams
[i
].bOut
;
1097 (*ppRet
)->nExceptions
= nExceptions
;
1098 (*ppRet
)->ppExceptions
= copyExceptions(nExceptions
, ppExceptionNames
);
1099 (*ppRet
)->pInterface
= pInterface
;
1100 (*ppRet
)->pBaseRef
= nullptr;
1102 (nAbsolutePosition
>= pInterface
->nAllMembers
- pInterface
->nMembers
)
1103 && nAbsolutePosition
< pInterface
->nAllMembers
);
1104 (*ppRet
)->nIndex
= nAbsolutePosition
1105 - (pInterface
->nAllMembers
- pInterface
->nMembers
);
1106 static_assert( TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( typelib_TypeClass_INTERFACE_METHOD
) );
1107 assert(reinterpret_cast<typelib_TypeDescription
*>(*ppRet
)->pWeakRef
== nullptr);
1111 extern "C" void SAL_CALL
typelib_typedescription_newInterfaceAttribute(
1112 typelib_InterfaceAttributeTypeDescription
** ppRet
,
1113 sal_Int32 nAbsolutePosition
,
1114 rtl_uString
* pTypeName
,
1115 typelib_TypeClass eAttributeTypeClass
,
1116 rtl_uString
* pAttributeTypeName
,
1117 sal_Bool bReadOnly
) noexcept
1119 typelib_typedescription_newExtendedInterfaceAttribute(
1120 ppRet
, nAbsolutePosition
, pTypeName
, eAttributeTypeClass
,
1121 pAttributeTypeName
, bReadOnly
, 0, nullptr, 0, nullptr);
1125 extern "C" void SAL_CALL
typelib_typedescription_newExtendedInterfaceAttribute(
1126 typelib_InterfaceAttributeTypeDescription
** ppRet
,
1127 sal_Int32 nAbsolutePosition
,
1128 rtl_uString
* pTypeName
,
1129 typelib_TypeClass eAttributeTypeClass
,
1130 rtl_uString
* pAttributeTypeName
,
1132 sal_Int32 nGetExceptions
, rtl_uString
** ppGetExceptionNames
,
1133 sal_Int32 nSetExceptions
, rtl_uString
** ppSetExceptionNames
) noexcept
1135 if (*ppRet
!= nullptr) {
1136 typelib_typedescription_release(&(*ppRet
)->aBase
.aBase
);
1139 sal_Int32 nOffset
= rtl_ustr_lastIndexOfChar_WithLength(
1140 pTypeName
->buffer
, pTypeName
->length
, ':');
1141 if (nOffset
<= 0 || pTypeName
->buffer
[nOffset
- 1] != ':') {
1142 OSL_FAIL("Bad interface attribute type name");
1145 OUString
aInterfaceTypeName(pTypeName
->buffer
, nOffset
- 1);
1146 typelib_InterfaceTypeDescription
* pInterface
= nullptr;
1147 typelib_typedescription_getByName(
1148 reinterpret_cast< typelib_TypeDescription
** >(&pInterface
),
1149 aInterfaceTypeName
.pData
);
1150 if (pInterface
== nullptr
1151 || pInterface
->aBase
.eTypeClass
!= typelib_TypeClass_INTERFACE
1153 reinterpret_cast< typelib_TypeDescription
** >(&pInterface
), false))
1155 OSL_FAIL("No interface corresponding to interface attribute");
1159 typelib_typedescription_newEmpty(
1160 reinterpret_cast<typelib_TypeDescription
**>(ppRet
), typelib_TypeClass_INTERFACE_ATTRIBUTE
, pTypeName
);
1162 rtl_uString_newFromStr_WithLength( &(*ppRet
)->aBase
.pMemberName
,
1163 pTypeName
->buffer
+ nOffset
+1,
1164 pTypeName
->length
- nOffset
-1 );
1165 (*ppRet
)->aBase
.nPosition
= nAbsolutePosition
;
1166 typelib_typedescriptionreference_new( &(*ppRet
)->pAttributeTypeRef
, eAttributeTypeClass
, pAttributeTypeName
);
1167 (*ppRet
)->bReadOnly
= bReadOnly
;
1168 (*ppRet
)->pInterface
= pInterface
;
1169 (*ppRet
)->pBaseRef
= nullptr;
1171 (nAbsolutePosition
>= pInterface
->nAllMembers
- pInterface
->nMembers
)
1172 && nAbsolutePosition
< pInterface
->nAllMembers
);
1173 (*ppRet
)->nIndex
= nAbsolutePosition
1174 - (pInterface
->nAllMembers
- pInterface
->nMembers
);
1175 (*ppRet
)->nGetExceptions
= nGetExceptions
;
1176 (*ppRet
)->ppGetExceptions
= copyExceptions(
1177 nGetExceptions
, ppGetExceptionNames
);
1178 (*ppRet
)->nSetExceptions
= nSetExceptions
;
1179 (*ppRet
)->ppSetExceptions
= copyExceptions(
1180 nSetExceptions
, ppSetExceptionNames
);
1181 static_assert( TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( typelib_TypeClass_INTERFACE_ATTRIBUTE
) );
1182 assert(reinterpret_cast<typelib_TypeDescription
*>(*ppRet
)->pWeakRef
== nullptr);
1186 extern "C" void SAL_CALL
typelib_typedescription_acquire(
1187 typelib_TypeDescription
* pTypeDescription
) noexcept
1189 osl_atomic_increment( &pTypeDescription
->nRefCount
);
1195 void deleteExceptions(
1196 sal_Int32 count
, typelib_TypeDescriptionReference
** exceptions
)
1198 for (sal_Int32 i
= 0; i
< count
; ++i
) {
1199 typelib_typedescriptionreference_release(exceptions
[i
]);
1201 delete[] exceptions
;
1206 // frees anything except typelib_TypeDescription base!
1207 static void typelib_typedescription_destructExtendedMembers(
1208 typelib_TypeDescription
* pTD
)
1210 OSL_ASSERT( typelib_TypeClass_TYPEDEF
!= pTD
->eTypeClass
);
1212 switch( pTD
->eTypeClass
)
1214 case typelib_TypeClass_SEQUENCE
:
1215 if( reinterpret_cast<typelib_IndirectTypeDescription
*>(pTD
)->pType
)
1216 typelib_typedescriptionreference_release( reinterpret_cast<typelib_IndirectTypeDescription
*>(pTD
)->pType
);
1218 case typelib_TypeClass_STRUCT
:
1219 delete[] reinterpret_cast< typelib_StructTypeDescription
* >(pTD
)->
1220 pParameterizedTypes
;
1222 case typelib_TypeClass_EXCEPTION
:
1224 typelib_CompoundTypeDescription
* pCTD
= reinterpret_cast<typelib_CompoundTypeDescription
*>(pTD
);
1225 if( pCTD
->pBaseTypeDescription
)
1226 typelib_typedescription_release( &pCTD
->pBaseTypeDescription
->aBase
);
1228 for( i
= 0; i
< pCTD
->nMembers
; i
++ )
1230 typelib_typedescriptionreference_release( pCTD
->ppTypeRefs
[i
] );
1232 if (pCTD
->ppMemberNames
)
1234 for ( i
= 0; i
< pCTD
->nMembers
; i
++ )
1236 rtl_uString_release( pCTD
->ppMemberNames
[i
] );
1238 delete [] pCTD
->ppMemberNames
;
1240 delete [] pCTD
->ppTypeRefs
;
1241 delete [] pCTD
->pMemberOffsets
;
1244 case typelib_TypeClass_INTERFACE
:
1246 typelib_InterfaceTypeDescription
* pITD
= reinterpret_cast<typelib_InterfaceTypeDescription
*>(pTD
);
1247 for( sal_Int32 i
= 0; i
< pITD
->nAllMembers
; i
++ )
1249 typelib_typedescriptionreference_release( pITD
->ppAllMembers
[i
] );
1251 delete [] pITD
->ppAllMembers
;
1252 delete [] pITD
->pMapMemberIndexToFunctionIndex
;
1253 delete [] pITD
->pMapFunctionIndexToMemberIndex
;
1254 for (sal_Int32 i
= 0; i
< pITD
->nBaseTypes
; ++i
) {
1255 typelib_typedescription_release(
1256 reinterpret_cast< typelib_TypeDescription
* >(
1257 pITD
->ppBaseTypes
[i
]));
1259 delete[] pITD
->ppBaseTypes
;
1262 case typelib_TypeClass_INTERFACE_METHOD
:
1264 typelib_InterfaceMethodTypeDescription
* pIMTD
= reinterpret_cast<typelib_InterfaceMethodTypeDescription
*>(pTD
);
1265 if( pIMTD
->pReturnTypeRef
)
1266 typelib_typedescriptionreference_release( pIMTD
->pReturnTypeRef
);
1267 for( sal_Int32 i
= 0; i
< pIMTD
->nParams
; i
++ )
1269 rtl_uString_release( pIMTD
->pParams
[ i
].pName
);
1270 typelib_typedescriptionreference_release( pIMTD
->pParams
[ i
].pTypeRef
);
1272 delete [] pIMTD
->pParams
;
1273 deleteExceptions(pIMTD
->nExceptions
, pIMTD
->ppExceptions
);
1274 rtl_uString_release( pIMTD
->aBase
.pMemberName
);
1275 typelib_typedescription_release(&pIMTD
->pInterface
->aBase
);
1276 if (pIMTD
->pBaseRef
!= nullptr) {
1277 typelib_typedescriptionreference_release(pIMTD
->pBaseRef
);
1281 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
1283 typelib_InterfaceAttributeTypeDescription
* pIATD
= reinterpret_cast<typelib_InterfaceAttributeTypeDescription
*>(pTD
);
1284 deleteExceptions(pIATD
->nGetExceptions
, pIATD
->ppGetExceptions
);
1285 deleteExceptions(pIATD
->nSetExceptions
, pIATD
->ppSetExceptions
);
1286 if( pIATD
->pAttributeTypeRef
)
1287 typelib_typedescriptionreference_release( pIATD
->pAttributeTypeRef
);
1288 if( pIATD
->aBase
.pMemberName
)
1289 rtl_uString_release( pIATD
->aBase
.pMemberName
);
1290 typelib_typedescription_release(&pIATD
->pInterface
->aBase
);
1291 if (pIATD
->pBaseRef
!= nullptr) {
1292 typelib_typedescriptionreference_release(pIATD
->pBaseRef
);
1296 case typelib_TypeClass_ENUM
:
1298 typelib_EnumTypeDescription
* pEnum
= reinterpret_cast<typelib_EnumTypeDescription
*>(pTD
);
1299 for ( sal_Int32 nPos
= pEnum
->nEnumValues
; nPos
--; )
1301 rtl_uString_release( pEnum
->ppEnumNames
[nPos
] );
1303 delete [] pEnum
->ppEnumNames
;
1304 delete [] pEnum
->pEnumValues
;
1313 extern "C" void SAL_CALL
typelib_typedescription_release(
1314 typelib_TypeDescription
* pTD
) noexcept
1316 sal_Int32 ref
= osl_atomic_decrement( &pTD
->nRefCount
);
1317 OSL_ASSERT(ref
>= 0);
1321 TypeDescriptor_Init_Impl
&rInit
= Init();
1322 if( TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( pTD
->eTypeClass
) )
1327 MutexGuard
aGuard( rInit
.maMutex
);
1328 // remove this description from the weak reference
1329 pTD
->pWeakRef
->pType
= nullptr;
1331 typelib_typedescriptionreference_release( pTD
->pWeakRef
);
1336 // this description is a reference too, so remove it from the hash table
1337 MutexGuard
aGuard( rInit
.maMutex
);
1338 WeakMap_Impl::iterator aIt
= rInit
.maWeakMap
.find( pTD
->pTypeName
->buffer
);
1339 if( aIt
!= rInit
.maWeakMap
.end() && static_cast<void *>((*aIt
).second
) == static_cast<void *>(pTD
) )
1341 // remove only if it contains the same object
1342 rInit
.maWeakMap
.erase( aIt
);
1346 typelib_typedescription_destructExtendedMembers( pTD
);
1347 rtl_uString_release( pTD
->pTypeName
);
1349 #if OSL_DEBUG_LEVEL > 0
1350 switch( pTD
->eTypeClass
)
1352 case typelib_TypeClass_SEQUENCE
:
1353 osl_atomic_decrement( &rInit
.nIndirectTypeDescriptionCount
);
1355 case typelib_TypeClass_STRUCT
:
1356 case typelib_TypeClass_EXCEPTION
:
1357 osl_atomic_decrement( &rInit
.nCompoundTypeDescriptionCount
);
1359 case typelib_TypeClass_INTERFACE
:
1360 osl_atomic_decrement( &rInit
.nInterfaceTypeDescriptionCount
);
1362 case typelib_TypeClass_INTERFACE_METHOD
:
1363 osl_atomic_decrement( &rInit
.nInterfaceMethodTypeDescriptionCount
);
1365 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
1366 osl_atomic_decrement( &rInit
.nInterfaceAttributeTypeDescriptionCount
);
1368 case typelib_TypeClass_ENUM
:
1369 osl_atomic_decrement( &rInit
.nEnumTypeDescriptionCount
);
1372 osl_atomic_decrement( &rInit
.nTypeDescriptionCount
);
1376 freeTypeDescription(pTD
);
1380 extern "C" void SAL_CALL
typelib_typedescription_register(
1381 typelib_TypeDescription
** ppNewDescription
) noexcept
1383 // connect the description with the weak reference
1384 TypeDescriptor_Init_Impl
&rInit
= Init();
1385 ClearableMutexGuard
aGuard( rInit
.maMutex
);
1387 typelib_TypeDescriptionReference
* pTDR
= nullptr;
1388 typelib_typedescriptionreference_getByName( &pTDR
, (*ppNewDescription
)->pTypeName
);
1390 OSL_ASSERT( (*ppNewDescription
)->pWeakRef
|| TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( (*ppNewDescription
)->eTypeClass
) );
1393 OSL_ASSERT( (*ppNewDescription
)->eTypeClass
== pTDR
->eTypeClass
);
1396 if (TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( pTDR
->eTypeClass
))
1398 // pRef->pType->pWeakRef == 0 means that the description is empty
1399 if (pTDR
->pType
->pWeakRef
)
1401 if (osl_atomic_increment( &pTDR
->pType
->nRefCount
) > 1)
1403 // The reference is incremented. The object cannot be destroyed.
1404 // Release the guard at the earliest point.
1406 ::typelib_typedescription_release( *ppNewDescription
);
1407 *ppNewDescription
= pTDR
->pType
;
1408 ::typelib_typedescriptionreference_release( pTDR
);
1411 // destruction of this type in progress (another thread!)
1412 (void)osl_atomic_decrement( &pTDR
->pType
->nRefCount
);
1415 pTDR
->pType
= *ppNewDescription
;
1416 OSL_ASSERT( ! (*ppNewDescription
)->pWeakRef
);
1417 (*ppNewDescription
)->pWeakRef
= pTDR
;
1422 if ((static_cast<void *>(pTDR
) != static_cast<void *>(*ppNewDescription
)) && // if different
1423 (!pTDR
->pType
->pWeakRef
|| // uninit: ref data only set
1424 // new one is complete:
1425 (!pTDR
->pType
->bComplete
&& (*ppNewDescription
)->bComplete
) ||
1426 // new one may be partly initialized interface (except of tables):
1427 (typelib_TypeClass_INTERFACE
== pTDR
->pType
->eTypeClass
&&
1428 !reinterpret_cast<typelib_InterfaceTypeDescription
*>(pTDR
->pType
)->ppAllMembers
&&
1429 (*reinterpret_cast<typelib_InterfaceTypeDescription
**>(ppNewDescription
))->ppAllMembers
)))
1431 // uninitialized or incomplete
1433 if (pTDR
->pType
->pWeakRef
) // if init
1435 switch (pTDR
->pType
->eTypeClass
) {
1436 case typelib_TypeClass_ENUM
:
1438 auto const src
= reinterpret_cast<typelib_EnumTypeDescription
*>(
1440 auto const dst
= reinterpret_cast<typelib_EnumTypeDescription
*>(
1442 assert(dst
->nEnumValues
== 0);
1443 assert(dst
->ppEnumNames
== nullptr);
1444 assert(dst
->pEnumValues
== nullptr);
1445 std::swap(src
->nEnumValues
, dst
->nEnumValues
);
1446 std::swap(src
->ppEnumNames
, dst
->ppEnumNames
);
1447 std::swap(src
->pEnumValues
, dst
->pEnumValues
);
1450 case typelib_TypeClass_STRUCT
:
1451 case typelib_TypeClass_EXCEPTION
:
1453 auto const src
= reinterpret_cast<typelib_CompoundTypeDescription
*>(
1455 auto const dst
= reinterpret_cast<typelib_CompoundTypeDescription
*>(
1458 (dst
->pBaseTypeDescription
== nullptr)
1459 == (src
->pBaseTypeDescription
== nullptr));
1460 assert(dst
->nMembers
== src
->nMembers
);
1461 assert((dst
->pMemberOffsets
== nullptr) == (dst
->nMembers
== 0));
1462 assert((dst
->ppTypeRefs
== nullptr) == (dst
->nMembers
== 0));
1463 assert(dst
->ppMemberNames
== nullptr);
1465 pTDR
->pType
->eTypeClass
!= typelib_TypeClass_STRUCT
1466 || ((reinterpret_cast<typelib_StructTypeDescription
*>(
1467 dst
)->pParameterizedTypes
1469 == (reinterpret_cast<typelib_StructTypeDescription
*>(
1470 src
)->pParameterizedTypes
1472 std::swap(src
->ppMemberNames
, dst
->ppMemberNames
);
1475 case typelib_TypeClass_INTERFACE
:
1477 auto const src
= reinterpret_cast<typelib_InterfaceTypeDescription
*>(
1479 auto const dst
= reinterpret_cast<typelib_InterfaceTypeDescription
*>(
1482 (dst
->pBaseTypeDescription
== nullptr)
1483 == (src
->pBaseTypeDescription
== nullptr));
1484 assert(dst
->nMembers
== 0);
1485 assert(dst
->ppMembers
== nullptr);
1486 assert(dst
->nAllMembers
== 0);
1487 assert(dst
->ppAllMembers
== nullptr);
1488 assert(dst
->pMapMemberIndexToFunctionIndex
== nullptr);
1489 assert(dst
->nMapFunctionIndexToMemberIndex
== 0);
1490 assert(dst
->pMapFunctionIndexToMemberIndex
== nullptr);
1491 assert(dst
->nBaseTypes
== src
->nBaseTypes
);
1492 assert((dst
->ppBaseTypes
== nullptr) == (src
->ppBaseTypes
== nullptr));
1493 std::swap(src
->nMembers
, dst
->nMembers
);
1494 std::swap(src
->ppMembers
, dst
->ppMembers
);
1495 std::swap(src
->nAllMembers
, dst
->nAllMembers
);
1496 std::swap(src
->ppAllMembers
, dst
->ppAllMembers
);
1498 src
->pMapMemberIndexToFunctionIndex
,
1499 dst
->pMapMemberIndexToFunctionIndex
);
1501 src
->nMapFunctionIndexToMemberIndex
,
1502 dst
->nMapFunctionIndexToMemberIndex
);
1504 src
->pMapFunctionIndexToMemberIndex
,
1505 dst
->pMapFunctionIndexToMemberIndex
);
1509 assert(false); // this cannot happen
1514 // pTDR->pType->pWeakRef == 0 means that the description is empty
1515 // description is not weak and the not the same
1516 sal_Int32 nSize
= getDescriptionSize( (*ppNewDescription
)->eTypeClass
);
1518 // copy all specific data for the descriptions
1521 *ppNewDescription
+1,
1522 nSize
- sizeof(typelib_TypeDescription
) );
1525 *ppNewDescription
+1,
1527 nSize
- sizeof( typelib_TypeDescription
) );
1530 pTDR
->pType
->bComplete
= (*ppNewDescription
)->bComplete
;
1531 pTDR
->pType
->nSize
= (*ppNewDescription
)->nSize
;
1532 pTDR
->pType
->nAlignment
= (*ppNewDescription
)->nAlignment
;
1534 if( pTDR
->pType
->bOnDemand
&& !(*ppNewDescription
)->bOnDemand
)
1536 // switch from OnDemand to !OnDemand, so the description must be acquired
1537 typelib_typedescription_acquire( pTDR
->pType
);
1539 else if( !pTDR
->pType
->bOnDemand
&& (*ppNewDescription
)->bOnDemand
)
1541 // switch from !OnDemand to OnDemand, so the description must be released
1542 assert(pTDR
->pType
->nRefCount
> 1);
1543 // coverity[freed_arg] - pType's nRefCount is > 1 here
1544 typelib_typedescription_release( pTDR
->pType
);
1547 pTDR
->pType
->bOnDemand
= (*ppNewDescription
)->bOnDemand
;
1549 pTDR
->pType
->pWeakRef
= pTDR
;
1552 typelib_typedescription_release( *ppNewDescription
);
1553 // pTDR was acquired by getByName(), so it must not be acquired again
1554 *ppNewDescription
= pTDR
->pType
;
1558 else if( TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( (*ppNewDescription
)->eTypeClass
) )
1560 typelib_typedescriptionreference_new(
1561 &pTDR
, (*ppNewDescription
)->eTypeClass
, (*ppNewDescription
)->pTypeName
);
1565 pTDR
= reinterpret_cast<typelib_TypeDescriptionReference
*>(*ppNewDescription
);
1567 // description is the weak itself, so register it
1568 rInit
.maWeakMap
[pTDR
->pTypeName
->buffer
] = pTDR
;
1569 OSL_ASSERT( static_cast<void *>(*ppNewDescription
) == static_cast<void *>(pTDR
) );
1572 // By default this reference is not really weak. The reference hold the description
1573 // and the description hold the reference.
1574 if( !(*ppNewDescription
)->bOnDemand
)
1576 // nor OnDemand so the description must be acquired if registered
1577 typelib_typedescription_acquire( *ppNewDescription
);
1580 pTDR
->pType
= *ppNewDescription
;
1581 (*ppNewDescription
)->pWeakRef
= pTDR
;
1582 OSL_ASSERT( rtl_ustr_compare( pTDR
->pTypeName
->buffer
, (*ppNewDescription
)->pTypeName
->buffer
) == 0 );
1583 OSL_ASSERT( pTDR
->eTypeClass
== (*ppNewDescription
)->eTypeClass
);
1587 static bool type_equals(
1588 typelib_TypeDescriptionReference
const * p1
, typelib_TypeDescriptionReference
const * p2
)
1591 (p1
->eTypeClass
== p2
->eTypeClass
&&
1592 p1
->pTypeName
->length
== p2
->pTypeName
->length
&&
1593 rtl_ustr_compare( p1
->pTypeName
->buffer
, p2
->pTypeName
->buffer
) == 0));
1595 extern "C" sal_Bool SAL_CALL
typelib_typedescription_equals(
1596 const typelib_TypeDescription
* p1
, const typelib_TypeDescription
* p2
) noexcept
1599 reinterpret_cast<typelib_TypeDescriptionReference
const *>(p1
), reinterpret_cast<typelib_TypeDescriptionReference
const *>(p2
) );
1603 extern "C" sal_Int32
typelib_typedescription_getAlignedUnoSize(
1604 const typelib_TypeDescription
* pTypeDescription
,
1605 sal_Int32 nOffset
, sal_Int32
& rMaxIntegralTypeSize
) noexcept
1608 if( pTypeDescription
->nSize
)
1610 // size and alignment are set
1611 rMaxIntegralTypeSize
= pTypeDescription
->nAlignment
;
1612 nSize
= pTypeDescription
->nSize
;
1617 rMaxIntegralTypeSize
= 1;
1619 OSL_ASSERT( typelib_TypeClass_TYPEDEF
!= pTypeDescription
->eTypeClass
);
1621 switch( pTypeDescription
->eTypeClass
)
1623 case typelib_TypeClass_INTERFACE
:
1624 // FEATURE_INTERFACE
1625 nSize
= rMaxIntegralTypeSize
= sal_Int32(sizeof( void * ));
1627 case typelib_TypeClass_ENUM
:
1628 nSize
= rMaxIntegralTypeSize
= sal_Int32(sizeof( typelib_TypeClass
));
1630 case typelib_TypeClass_STRUCT
:
1631 case typelib_TypeClass_EXCEPTION
:
1632 // FEATURE_EMPTYCLASS
1634 typelib_CompoundTypeDescription
const * pTmp
= reinterpret_cast<typelib_CompoundTypeDescription
const *>(pTypeDescription
);
1635 sal_Int32 nStructSize
= 0;
1636 if( pTmp
->pBaseTypeDescription
)
1638 // inherit structs extends the base struct.
1639 nStructSize
= pTmp
->pBaseTypeDescription
->aBase
.nSize
;
1640 rMaxIntegralTypeSize
= pTmp
->pBaseTypeDescription
->aBase
.nAlignment
;
1642 for( sal_Int32 i
= 0; i
< pTmp
->nMembers
; i
++ )
1644 typelib_TypeDescription
* pMemberType
= nullptr;
1645 typelib_TypeDescriptionReference
* pMemberRef
= pTmp
->ppTypeRefs
[i
];
1647 sal_Int32 nMaxIntegral
;
1648 if (pMemberRef
->eTypeClass
== typelib_TypeClass_INTERFACE
1649 || pMemberRef
->eTypeClass
== typelib_TypeClass_SEQUENCE
)
1651 nMaxIntegral
= sal_Int32(sizeof(void *));
1652 nStructSize
= newAlignedSize( nStructSize
, nMaxIntegral
, nMaxIntegral
);
1656 TYPELIB_DANGER_GET( &pMemberType
, pMemberRef
);
1657 nStructSize
= typelib_typedescription_getAlignedUnoSize(
1658 pMemberType
, nStructSize
, nMaxIntegral
);
1659 TYPELIB_DANGER_RELEASE( pMemberType
);
1661 if( nMaxIntegral
> rMaxIntegralTypeSize
)
1662 rMaxIntegralTypeSize
= nMaxIntegral
;
1665 // Anything that is at least 16 bits wide is aligned on a 16-bit
1666 // boundary on the m68k default abi
1667 sal_Int32 nMaxAlign
= std::min(rMaxIntegralTypeSize
, sal_Int32( 2 ));
1668 nStructSize
= (nStructSize
+ nMaxAlign
-1) / nMaxAlign
* nMaxAlign
;
1670 // Example: A { double; int; } structure has a size of 16 instead of 10. The
1671 // compiler must follow this rule if it is possible to access members in arrays through:
1672 // (Element *)((char *)pArray + sizeof( Element ) * ElementPos)
1673 nStructSize
= (nStructSize
+ rMaxIntegralTypeSize
-1)
1674 / rMaxIntegralTypeSize
* rMaxIntegralTypeSize
;
1676 nSize
+= nStructSize
;
1679 case typelib_TypeClass_SEQUENCE
:
1680 nSize
= rMaxIntegralTypeSize
= sal_Int32(sizeof( void * ));
1682 case typelib_TypeClass_ANY
:
1684 nSize
= sal_Int32(sizeof( uno_Any
));
1685 rMaxIntegralTypeSize
= sal_Int32(sizeof( void * ));
1687 case typelib_TypeClass_TYPE
:
1688 nSize
= rMaxIntegralTypeSize
= sal_Int32(sizeof( typelib_TypeDescriptionReference
* ));
1690 case typelib_TypeClass_BOOLEAN
:
1691 nSize
= rMaxIntegralTypeSize
= sal_Int32(sizeof( sal_Bool
));
1693 case typelib_TypeClass_CHAR
:
1694 nSize
= rMaxIntegralTypeSize
= sal_Int32(sizeof( sal_Unicode
));
1696 case typelib_TypeClass_STRING
:
1698 nSize
= rMaxIntegralTypeSize
= sal_Int32(sizeof( rtl_uString
* ));
1700 case typelib_TypeClass_FLOAT
:
1701 nSize
= rMaxIntegralTypeSize
= sal_Int32(sizeof( float ));
1703 case typelib_TypeClass_DOUBLE
:
1704 nSize
= rMaxIntegralTypeSize
= sal_Int32(sizeof( double ));
1706 case typelib_TypeClass_BYTE
:
1707 nSize
= rMaxIntegralTypeSize
= sal_Int32(sizeof( sal_Int8
));
1709 case typelib_TypeClass_SHORT
:
1710 case typelib_TypeClass_UNSIGNED_SHORT
:
1711 nSize
= rMaxIntegralTypeSize
= sal_Int32(sizeof( sal_Int16
));
1713 case typelib_TypeClass_LONG
:
1714 case typelib_TypeClass_UNSIGNED_LONG
:
1715 nSize
= rMaxIntegralTypeSize
= sal_Int32(sizeof( sal_Int32
));
1717 case typelib_TypeClass_HYPER
:
1718 case typelib_TypeClass_UNSIGNED_HYPER
:
1719 nSize
= rMaxIntegralTypeSize
= sal_Int32(sizeof( sal_Int64
));
1721 case typelib_TypeClass_UNKNOWN
:
1722 case typelib_TypeClass_SERVICE
:
1723 case typelib_TypeClass_MODULE
:
1725 OSL_FAIL( "not convertible type" );
1729 return newAlignedSize( nOffset
, nSize
, rMaxIntegralTypeSize
);
1735 typelib_TypeDescriptionReference
** copyExceptions(
1736 sal_Int32 count
, typelib_TypeDescriptionReference
** source
)
1738 typelib_TypeDescriptionReference
** p
1739 = new typelib_TypeDescriptionReference
*[count
];
1740 for (sal_Int32 i
= 0; i
< count
; ++i
) {
1742 typelib_typedescriptionreference_acquire(p
[i
]);
1747 bool createDerivedInterfaceMemberDescription(
1748 typelib_TypeDescription
** result
, OUString
const & name
,
1749 typelib_TypeDescriptionReference
* baseRef
,
1750 typelib_TypeDescription
const * base
, typelib_TypeDescription
* interface
,
1751 sal_Int32 index
, sal_Int32 position
)
1753 if (!baseRef
|| !base
|| !interface
)
1756 switch (base
->eTypeClass
) {
1757 case typelib_TypeClass_INTERFACE_METHOD
:
1759 typelib_typedescription_newEmpty(
1760 result
, typelib_TypeClass_INTERFACE_METHOD
, name
.pData
);
1761 typelib_InterfaceMethodTypeDescription
const * baseMethod
1763 typelib_InterfaceMethodTypeDescription
const * >(base
);
1764 typelib_InterfaceMethodTypeDescription
* newMethod
1766 typelib_InterfaceMethodTypeDescription
* >(*result
);
1767 newMethod
->aBase
.nPosition
= position
;
1768 newMethod
->aBase
.pMemberName
1769 = baseMethod
->aBase
.pMemberName
;
1770 rtl_uString_acquire(
1771 newMethod
->aBase
.pMemberName
);
1772 newMethod
->pReturnTypeRef
= baseMethod
->pReturnTypeRef
;
1773 typelib_typedescriptionreference_acquire(
1774 newMethod
->pReturnTypeRef
);
1775 newMethod
->nParams
= baseMethod
->nParams
;
1776 newMethod
->pParams
= new typelib_MethodParameter
[
1777 newMethod
->nParams
];
1778 for (sal_Int32 i
= 0; i
< newMethod
->nParams
; ++i
) {
1779 newMethod
->pParams
[i
].pName
1780 = baseMethod
->pParams
[i
].pName
;
1781 rtl_uString_acquire(
1782 newMethod
->pParams
[i
].pName
);
1783 newMethod
->pParams
[i
].pTypeRef
1784 = baseMethod
->pParams
[i
].pTypeRef
;
1785 typelib_typedescriptionreference_acquire(
1786 newMethod
->pParams
[i
].pTypeRef
);
1787 newMethod
->pParams
[i
].bIn
= baseMethod
->pParams
[i
].bIn
;
1788 newMethod
->pParams
[i
].bOut
= baseMethod
->pParams
[i
].bOut
;
1790 newMethod
->nExceptions
= baseMethod
->nExceptions
;
1791 newMethod
->ppExceptions
= copyExceptions(
1792 baseMethod
->nExceptions
, baseMethod
->ppExceptions
);
1793 newMethod
->bOneWay
= baseMethod
->bOneWay
;
1794 newMethod
->pInterface
1795 = reinterpret_cast< typelib_InterfaceTypeDescription
* >(
1797 newMethod
->pBaseRef
= baseRef
;
1798 newMethod
->nIndex
= index
;
1802 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
1804 typelib_typedescription_newEmpty(
1805 result
, typelib_TypeClass_INTERFACE_ATTRIBUTE
, name
.pData
);
1806 typelib_InterfaceAttributeTypeDescription
const * baseAttribute
1808 typelib_InterfaceAttributeTypeDescription
const * >(base
);
1809 typelib_InterfaceAttributeTypeDescription
* newAttribute
1811 typelib_InterfaceAttributeTypeDescription
* >(*result
);
1812 newAttribute
->aBase
.nPosition
= position
;
1813 newAttribute
->aBase
.pMemberName
1814 = baseAttribute
->aBase
.pMemberName
;
1815 rtl_uString_acquire(newAttribute
->aBase
.pMemberName
);
1816 newAttribute
->bReadOnly
= baseAttribute
->bReadOnly
;
1817 newAttribute
->pAttributeTypeRef
1818 = baseAttribute
->pAttributeTypeRef
;
1819 typelib_typedescriptionreference_acquire(newAttribute
->pAttributeTypeRef
);
1820 newAttribute
->pInterface
1821 = reinterpret_cast< typelib_InterfaceTypeDescription
* >(
1823 newAttribute
->pBaseRef
= baseRef
;
1824 newAttribute
->nIndex
= index
;
1825 newAttribute
->nGetExceptions
= baseAttribute
->nGetExceptions
;
1826 newAttribute
->ppGetExceptions
= copyExceptions(
1827 baseAttribute
->nGetExceptions
,
1828 baseAttribute
->ppGetExceptions
);
1829 newAttribute
->nSetExceptions
= baseAttribute
->nSetExceptions
;
1830 newAttribute
->ppSetExceptions
= copyExceptions(
1831 baseAttribute
->nSetExceptions
,
1832 baseAttribute
->ppSetExceptions
);
1844 extern "C" void SAL_CALL
typelib_typedescription_getByName(
1845 typelib_TypeDescription
** ppRet
, rtl_uString
* pName
) noexcept
1849 typelib_typedescription_release( *ppRet
);
1853 static bool bInited
= false;
1854 TypeDescriptor_Init_Impl
&rInit
= Init();
1858 // guard against multi thread access
1859 MutexGuard
aGuard( rInit
.maMutex
);
1862 // avoid recursion during the next ...new calls
1865 typelib_TypeDescription
* pType
= nullptr;
1866 typelib_typedescription_new( &pType
, typelib_TypeClass_TYPE
, u
"type"_ustr
.pData
, nullptr, 0, nullptr );
1867 typelib_typedescription_register( &pType
);
1868 typelib_typedescription_new( &pType
, typelib_TypeClass_VOID
, u
"void"_ustr
.pData
, nullptr, 0, nullptr );
1869 typelib_typedescription_register( &pType
);
1870 typelib_typedescription_new( &pType
, typelib_TypeClass_BOOLEAN
, u
"boolean"_ustr
.pData
, nullptr, 0, nullptr );
1871 typelib_typedescription_register( &pType
);
1872 typelib_typedescription_new( &pType
, typelib_TypeClass_CHAR
, u
"char"_ustr
.pData
, nullptr, 0, nullptr );
1873 typelib_typedescription_register( &pType
);
1874 typelib_typedescription_new( &pType
, typelib_TypeClass_BYTE
, u
"byte"_ustr
.pData
, nullptr, 0, nullptr );
1875 typelib_typedescription_register( &pType
);
1876 typelib_typedescription_new( &pType
, typelib_TypeClass_STRING
, u
"string"_ustr
.pData
, nullptr, 0, nullptr );
1877 typelib_typedescription_register( &pType
);
1878 typelib_typedescription_new( &pType
, typelib_TypeClass_SHORT
, u
"short"_ustr
.pData
, nullptr, 0, nullptr );
1879 typelib_typedescription_register( &pType
);
1880 typelib_typedescription_new( &pType
, typelib_TypeClass_UNSIGNED_SHORT
, u
"unsigned short"_ustr
.pData
, nullptr, 0, nullptr );
1881 typelib_typedescription_register( &pType
);
1882 typelib_typedescription_new( &pType
, typelib_TypeClass_LONG
, u
"long"_ustr
.pData
, nullptr, 0, nullptr );
1883 typelib_typedescription_register( &pType
);
1884 typelib_typedescription_new( &pType
, typelib_TypeClass_UNSIGNED_LONG
, u
"unsigned long"_ustr
.pData
, nullptr, 0, nullptr );
1885 typelib_typedescription_register( &pType
);
1886 typelib_typedescription_new( &pType
, typelib_TypeClass_HYPER
, u
"hyper"_ustr
.pData
, nullptr, 0, nullptr );
1887 typelib_typedescription_register( &pType
);
1888 typelib_typedescription_new( &pType
, typelib_TypeClass_UNSIGNED_HYPER
, u
"unsigned hyper"_ustr
.pData
, nullptr, 0, nullptr );
1889 typelib_typedescription_register( &pType
);
1890 typelib_typedescription_new( &pType
, typelib_TypeClass_FLOAT
, u
"float"_ustr
.pData
, nullptr, 0, nullptr );
1891 typelib_typedescription_register( &pType
);
1892 typelib_typedescription_new( &pType
, typelib_TypeClass_DOUBLE
, u
"double"_ustr
.pData
, nullptr, 0, nullptr );
1893 typelib_typedescription_register( &pType
);
1894 typelib_typedescription_new( &pType
, typelib_TypeClass_ANY
, u
"any"_ustr
.pData
, nullptr, 0, nullptr );
1895 typelib_typedescription_register( &pType
);
1896 typelib_typedescription_release( pType
);
1900 typelib_TypeDescriptionReference
* pTDR
= nullptr;
1901 typelib_typedescriptionreference_getByName( &pTDR
, pName
);
1905 // guard against multi thread access
1906 MutexGuard
aGuard( rInit
.maMutex
);
1907 // pTDR->pType->pWeakRef == 0 means that the description is empty
1908 if( pTDR
->pType
&& pTDR
->pType
->pWeakRef
)
1910 typelib_typedescription_acquire( pTDR
->pType
);
1911 *ppRet
= pTDR
->pType
;
1914 typelib_typedescriptionreference_release( pTDR
);
1917 if (nullptr != *ppRet
)
1920 // check for sequence
1921 OUString
const & name
= OUString::unacquired( &pName
);
1922 if (2 < name
.getLength() && '[' == name
[ 0 ])
1924 OUString
element_name( name
.copy( 2 ) );
1925 typelib_TypeDescription
* element_td
= nullptr;
1926 typelib_typedescription_getByName( &element_td
, element_name
.pData
);
1927 if (nullptr != element_td
)
1929 typelib_typedescription_new(
1930 ppRet
, typelib_TypeClass_SEQUENCE
, pName
, element_td
->pWeakRef
, 0, nullptr );
1932 typelib_typedescription_release( element_td
);
1935 if (nullptr == *ppRet
)
1937 // Check for derived interface member type:
1938 sal_Int32 i1
= name
.lastIndexOf(":@");
1940 sal_Int32 i2
= i1
+ RTL_CONSTASCII_LENGTH(":@");
1941 sal_Int32 i3
= name
.indexOf(',', i2
);
1943 sal_Int32 i4
= name
.indexOf(':', i3
);
1945 typelib_TypeDescriptionReference
* pBaseRef
= nullptr;
1946 typelib_TypeDescription
* pBase
= nullptr;
1947 typelib_TypeDescription
* pInterface
= nullptr;
1948 typelib_typedescriptionreference_getByName(
1949 &pBaseRef
, name
.copy(0, i1
).pData
);
1950 if (pBaseRef
!= nullptr) {
1951 typelib_typedescriptionreference_getDescription(
1954 typelib_typedescription_getByName(
1955 &pInterface
, name
.copy(i4
+ 1).pData
);
1956 if (!createDerivedInterfaceMemberDescription(
1957 ppRet
, name
, pBaseRef
, pBase
, pInterface
,
1958 o3tl::toInt32(name
.subView(i2
, i3
- i2
)),
1959 o3tl::toInt32(name
.subView(i3
+ 1, i4
- i3
- 1))))
1961 if (pInterface
!= nullptr) {
1962 typelib_typedescription_release(pInterface
);
1964 if (pBase
!= nullptr) {
1965 typelib_typedescription_release(pBase
);
1967 if (pBaseRef
!= nullptr) {
1968 typelib_typedescriptionreference_release(
1976 if (nullptr == *ppRet
)
1979 rInit
.callChain( ppRet
, pName
);
1985 // typedescription found
1986 if (typelib_TypeClass_TYPEDEF
== (*ppRet
)->eTypeClass
)
1988 typelib_TypeDescription
* pTD
= nullptr;
1989 typelib_typedescriptionreference_getDescription(
1990 &pTD
, reinterpret_cast<typelib_IndirectTypeDescription
*>(*ppRet
)->pType
);
1991 typelib_typedescription_release( *ppRet
);
1997 (*ppRet
)->bOnDemand
= true;
1998 // The type description is hold by the reference until
1999 // on demand is activated.
2000 typelib_typedescription_register( ppRet
);
2002 // insert into the cache
2003 MutexGuard
aGuard( rInit
.maMutex
);
2004 if( rInit
.maCache
.size() >= nCacheSize
)
2006 typelib_typedescription_release( rInit
.maCache
.front() );
2007 rInit
.maCache
.pop_front();
2009 // descriptions in the cache must be acquired!
2010 typelib_typedescription_acquire( *ppRet
);
2011 rInit
.maCache
.push_back( *ppRet
);
2015 extern "C" void SAL_CALL
typelib_typedescriptionreference_newByAsciiName(
2016 typelib_TypeDescriptionReference
** ppTDR
,
2017 typelib_TypeClass eTypeClass
,
2018 const char * pTypeName
) noexcept
2020 OUString
aTypeName( OUString::createFromAscii( pTypeName
) );
2021 typelib_typedescriptionreference_new( ppTDR
, eTypeClass
, aTypeName
.pData
);
2024 extern "C" void SAL_CALL
typelib_typedescriptionreference_new(
2025 typelib_TypeDescriptionReference
** ppTDR
,
2026 typelib_TypeClass eTypeClass
, rtl_uString
* pTypeName
) noexcept
2028 TypeDescriptor_Init_Impl
&rInit
= Init();
2029 if( eTypeClass
== typelib_TypeClass_TYPEDEF
)
2032 typelib_TypeDescription
* pRet
= nullptr;
2033 rInit
.callChain( &pRet
, pTypeName
);
2036 // typedescription found
2037 if (typelib_TypeClass_TYPEDEF
== pRet
->eTypeClass
)
2039 typelib_typedescriptionreference_acquire(
2040 reinterpret_cast<typelib_IndirectTypeDescription
*>(pRet
)->pType
);
2042 typelib_typedescriptionreference_release( *ppTDR
);
2043 *ppTDR
= reinterpret_cast<typelib_IndirectTypeDescription
*>(pRet
)->pType
;
2044 typelib_typedescription_release( pRet
);
2049 pRet
->bOnDemand
= true;
2050 // The type description is hold by the reference until
2051 // on demand is activated.
2052 typelib_typedescription_register( &pRet
);
2054 // insert into the cache
2055 MutexGuard
aGuard( rInit
.maMutex
);
2056 if( rInit
.maCache
.size() >= nCacheSize
)
2058 typelib_typedescription_release( rInit
.maCache
.front() );
2059 rInit
.maCache
.pop_front();
2061 rInit
.maCache
.push_back( pRet
);
2062 // pRet kept acquired for cache
2064 typelib_typedescriptionreference_acquire( pRet
->pWeakRef
);
2066 typelib_typedescriptionreference_release( *ppTDR
);
2067 *ppTDR
= pRet
->pWeakRef
;
2072 SAL_INFO("cppu.typelib", "typedef not found : " << pTypeName
);
2073 typelib_typedescriptionreference_release( *ppTDR
);
2079 MutexGuard
aGuard( rInit
.maMutex
);
2080 typelib_typedescriptionreference_getByName( ppTDR
, pTypeName
);
2084 if( TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( eTypeClass
) )
2086 typelib_TypeDescriptionReference
* pTDR
= new typelib_TypeDescriptionReference
;
2087 #if OSL_DEBUG_LEVEL > 0
2088 osl_atomic_increment( &rInit
.nTypeDescriptionReferenceCount
);
2090 pTDR
->nRefCount
= 1;
2091 pTDR
->nStaticRefCount
= 0;
2092 pTDR
->eTypeClass
= eTypeClass
;
2093 pTDR
->pUniqueIdentifier
= nullptr;
2094 pTDR
->pReserved
= nullptr;
2095 pTDR
->pTypeName
= pTypeName
;
2096 rtl_uString_acquire( pTDR
->pTypeName
);
2097 pTDR
->pType
= nullptr;
2102 typelib_typedescription_newEmpty( reinterpret_cast<typelib_TypeDescription
** >(ppTDR
), eTypeClass
, pTypeName
);
2103 // description will be registered but not acquired
2104 (*reinterpret_cast<typelib_TypeDescription
**>(ppTDR
))->bOnDemand
= true;
2105 (*reinterpret_cast<typelib_TypeDescription
**>(ppTDR
))->bComplete
= false;
2108 // Heavy hack, the const sal_Unicode * is hold by the typedescription reference
2110 rInit
.maWeakMap
[ (*ppTDR
)->pTypeName
->buffer
] = *ppTDR
;
2114 extern "C" void SAL_CALL
typelib_typedescriptionreference_acquire(
2115 typelib_TypeDescriptionReference
* pRef
) noexcept
2117 osl_atomic_increment( &pRef
->nRefCount
);
2121 extern "C" void SAL_CALL
typelib_typedescriptionreference_release(
2122 typelib_TypeDescriptionReference
* pRef
) noexcept
2124 // Is it a type description?
2125 if( TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( pRef
->eTypeClass
) )
2127 if( ! osl_atomic_decrement( &pRef
->nRefCount
) )
2129 TypeDescriptor_Init_Impl
&rInit
= Init();
2130 MutexGuard
aGuard( rInit
.maMutex
);
2131 WeakMap_Impl::iterator aIt
= rInit
.maWeakMap
.find( pRef
->pTypeName
->buffer
);
2132 if( aIt
!= rInit
.maWeakMap
.end() && (*aIt
).second
== pRef
)
2134 // remove only if it contains the same object
2135 rInit
.maWeakMap
.erase( aIt
);
2138 rtl_uString_release( pRef
->pTypeName
);
2139 OSL_ASSERT( pRef
->pType
== nullptr );
2140 #if OSL_DEBUG_LEVEL > 0
2141 osl_atomic_decrement( &rInit
.nTypeDescriptionReferenceCount
);
2148 typelib_typedescription_release( reinterpret_cast<typelib_TypeDescription
*>(pRef
) );
2153 extern "C" void SAL_CALL
typelib_typedescriptionreference_getDescription(
2154 typelib_TypeDescription
** ppRet
, typelib_TypeDescriptionReference
* pRef
) noexcept
2158 typelib_typedescription_release( *ppRet
);
2162 if( !TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( pRef
->eTypeClass
) && pRef
->pType
&& pRef
->pType
->pWeakRef
)
2164 // reference is a description and initialized
2165 osl_atomic_increment( &reinterpret_cast<typelib_TypeDescription
*>(pRef
)->nRefCount
);
2166 *ppRet
= reinterpret_cast<typelib_TypeDescription
*>(pRef
);
2171 MutexGuard
aGuard( Init().maMutex
);
2172 // pRef->pType->pWeakRef == 0 means that the description is empty
2173 if( pRef
->pType
&& pRef
->pType
->pWeakRef
)
2175 sal_Int32 n
= osl_atomic_increment( &pRef
->pType
->nRefCount
);
2178 // The reference is incremented. The object cannot be destroyed.
2179 // Release the guard at the earliest point.
2180 *ppRet
= pRef
->pType
;
2183 (void)osl_atomic_decrement( &pRef
->pType
->nRefCount
);
2184 // destruction of this type in progress (another thread!)
2185 // no access through this weak reference
2186 pRef
->pType
= nullptr;
2190 typelib_typedescription_getByName( ppRet
, pRef
->pTypeName
);
2191 OSL_ASSERT( !*ppRet
|| rtl_ustr_compare( pRef
->pTypeName
->buffer
, (*ppRet
)->pTypeName
->buffer
) == 0 );
2192 OSL_ASSERT( !*ppRet
|| pRef
->eTypeClass
== (*ppRet
)->eTypeClass
);
2193 OSL_ASSERT( !*ppRet
|| pRef
== (*ppRet
)->pWeakRef
);
2194 pRef
->pType
= *ppRet
;
2198 extern "C" void typelib_typedescriptionreference_getByName(
2199 typelib_TypeDescriptionReference
** ppRet
, rtl_uString
const * pName
) noexcept
2203 typelib_typedescriptionreference_release( *ppRet
);
2206 TypeDescriptor_Init_Impl
&rInit
= Init();
2208 MutexGuard
aGuard( rInit
.maMutex
);
2209 WeakMap_Impl::const_iterator aIt
= rInit
.maWeakMap
.find( pName
->buffer
);
2210 if( aIt
== rInit
.maWeakMap
.end() )
2213 sal_Int32 n
= osl_atomic_increment( &(*aIt
).second
->nRefCount
);
2216 // The reference is incremented. The object cannot be destroyed.
2217 // Release the guard at the earliest point.
2218 *ppRet
= (*aIt
).second
;
2222 // destruction of this type in progress (another thread!)
2223 // no access through this weak reference
2224 (void)osl_atomic_decrement( &(*aIt
).second
->nRefCount
);
2229 extern "C" sal_Bool SAL_CALL
typelib_typedescriptionreference_equals(
2230 const typelib_TypeDescriptionReference
* p1
,
2231 const typelib_TypeDescriptionReference
* p2
) noexcept
2234 (p1
->eTypeClass
== p2
->eTypeClass
&&
2235 p1
->pTypeName
->length
== p2
->pTypeName
->length
&&
2236 rtl_ustr_compare( p1
->pTypeName
->buffer
, p2
->pTypeName
->buffer
) == 0));
2240 extern "C" void SAL_CALL
typelib_typedescriptionreference_assign(
2241 typelib_TypeDescriptionReference
** ppDest
,
2242 typelib_TypeDescriptionReference
* pSource
) noexcept
2244 if (*ppDest
!= pSource
)
2246 ::typelib_typedescriptionreference_acquire( pSource
);
2247 ::typelib_typedescriptionreference_release( *ppDest
);
2253 extern "C" void SAL_CALL
typelib_setCacheSize( sal_Int32
) noexcept
2258 const bool s_aAssignableFromTab
[11][11] =
2260 /* from CH, BO, BY, SH, US, LO, UL, HY, UH, FL, DO */
2261 /* TypeClass_CHAR */ { true, false, false, false, false, false, false, false, false, false, false },
2262 /* TypeClass_BOOLEAN */ { false, true, false, false, false, false, false, false, false, false, false },
2263 /* TypeClass_BYTE */ { false, false, true, false, false, false, false, false, false, false, false },
2264 /* TypeClass_SHORT */ { false, false, true, true, true, false, false, false, false, false, false },
2265 /* TypeClass_UNSIGNED_SHORT */ { false, false, true, true, true, false, false, false, false, false, false },
2266 /* TypeClass_LONG */ { false, false, true, true, true, true, true, false, false, false, false },
2267 /* TypeClass_UNSIGNED_LONG */ { false, false, true, true, true, true, true, false, false, false, false },
2268 /* TypeClass_HYPER */ { false, false, true, true, true, true, true, true, true, false, false },
2269 /* TypeClass_UNSIGNED_HYPER */ { false, false, true, true, true, true, true, true, true, false, false },
2270 /* TypeClass_FLOAT */ { false, false, true, true, true, false, false, false, false, true, false },
2271 /* TypeClass_DOUBLE */ { false, false, true, true, true, true, true, false, false, true, true }
2275 extern "C" sal_Bool SAL_CALL
typelib_typedescriptionreference_isAssignableFrom(
2276 typelib_TypeDescriptionReference
* pAssignable
,
2277 typelib_TypeDescriptionReference
* pFrom
) noexcept
2279 if (!pAssignable
|| !pFrom
)
2282 typelib_TypeClass eAssignable
= pAssignable
->eTypeClass
;
2283 typelib_TypeClass eFrom
= pFrom
->eTypeClass
;
2285 if (eAssignable
== typelib_TypeClass_ANY
) // anything can be assigned to an any .)
2287 if (eAssignable
== eFrom
)
2289 if (type_equals( pAssignable
, pFrom
)) // first shot
2293 switch (eAssignable
)
2295 case typelib_TypeClass_STRUCT
:
2296 case typelib_TypeClass_EXCEPTION
:
2298 typelib_TypeDescription
* pFromDescr
= nullptr;
2299 TYPELIB_DANGER_GET( &pFromDescr
, pFrom
);
2300 if (!reinterpret_cast<typelib_CompoundTypeDescription
*>(pFromDescr
)->pBaseTypeDescription
)
2302 TYPELIB_DANGER_RELEASE( pFromDescr
);
2305 bool bRet
= typelib_typedescriptionreference_isAssignableFrom(
2307 reinterpret_cast<typelib_CompoundTypeDescription
*>(pFromDescr
)->pBaseTypeDescription
->aBase
.pWeakRef
);
2308 TYPELIB_DANGER_RELEASE( pFromDescr
);
2311 case typelib_TypeClass_INTERFACE
:
2313 typelib_TypeDescription
* pFromDescr
= nullptr;
2314 TYPELIB_DANGER_GET( &pFromDescr
, pFrom
);
2315 typelib_InterfaceTypeDescription
* pFromIfc
2317 typelib_InterfaceTypeDescription
* >(pFromDescr
);
2319 for (sal_Int32 i
= 0; i
< pFromIfc
->nBaseTypes
; ++i
) {
2320 if (typelib_typedescriptionreference_isAssignableFrom(
2322 pFromIfc
->ppBaseTypes
[i
]->aBase
.pWeakRef
))
2328 TYPELIB_DANGER_RELEASE( pFromDescr
);
2337 return (eAssignable
>= typelib_TypeClass_CHAR
&& eAssignable
<= typelib_TypeClass_DOUBLE
&&
2338 eFrom
>= typelib_TypeClass_CHAR
&& eFrom
<= typelib_TypeClass_DOUBLE
&&
2339 s_aAssignableFromTab
[eAssignable
-1][eFrom
-1]);
2342 extern "C" sal_Bool SAL_CALL
typelib_typedescription_isAssignableFrom(
2343 typelib_TypeDescription
* pAssignable
,
2344 typelib_TypeDescription
* pFrom
) noexcept
2346 return typelib_typedescriptionreference_isAssignableFrom(
2347 pAssignable
->pWeakRef
, pFrom
->pWeakRef
);
2351 extern "C" sal_Bool SAL_CALL
typelib_typedescription_complete(
2352 typelib_TypeDescription
** ppTypeDescr
) noexcept
2354 return complete(ppTypeDescr
, true);
2357 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */