Update git submodules
[LibreOffice.git] / cppu / source / typelib / static_types.cxx
blobc5af49b7164f3ea752ebfc0c206ab2a9d7317496
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>
22 #include <algorithm>
23 #include <cassert>
25 #include <osl/mutex.hxx>
26 #include <rtl/ustring.hxx>
28 #include <typelib/typedescription.h>
29 #include "typelib.hxx"
32 using namespace osl;
34 namespace
36 Mutex& typelib_StaticInitMutex()
38 static Mutex SINGLETON;
39 return SINGLETON;
43 extern "C"
47 #ifdef _WIN32
48 #pragma pack(push, 8)
49 #endif
51 namespace {
53 /**
54 * The double member determines the alignment.
55 * Under OS2 and MS-Windows the Alignment is min( 8, sizeof( type ) ).
56 * The alignment of a structure is min( 8, sizeof( max basic type ) ), the greatest basic type
57 * determines the alignment.
59 struct AlignSize_Impl
61 sal_Int16 nInt16;
62 double dDouble;
67 #ifdef _WIN32
68 #pragma pack(pop)
69 #endif
71 // the value of the maximal alignment
72 const sal_Int32 nMaxAlignment = static_cast<sal_Int32>( reinterpret_cast<sal_Size>(&reinterpret_cast<AlignSize_Impl *>(16)->dDouble) - 16);
74 static sal_Int32 adjustAlignment( sal_Int32 nRequestedAlignment )
76 if( nRequestedAlignment > nMaxAlignment )
77 nRequestedAlignment = nMaxAlignment;
78 return nRequestedAlignment;
81 /**
82 * Calculate the new size of the struktur.
84 static sal_Int32 newAlignedSize(
85 sal_Int32 OldSize, sal_Int32 ElementSize, sal_Int32 NeededAlignment )
87 NeededAlignment = adjustAlignment( NeededAlignment );
88 return (OldSize + NeededAlignment -1) / NeededAlignment * NeededAlignment + ElementSize;
92 // !for NOT REALLY WEAK TYPES only!
93 static typelib_TypeDescriptionReference * igetTypeByName( rtl_uString const * pTypeName )
95 typelib_TypeDescriptionReference * pRef = nullptr;
96 ::typelib_typedescriptionreference_getByName( &pRef, pTypeName );
97 if (pRef && pRef->pType && pRef->pType->pWeakRef) // found initialized td
99 return pRef;
101 return nullptr;
104 extern "C"
107 typelib_TypeDescriptionReference ** SAL_CALL typelib_static_type_getByTypeClass(
108 typelib_TypeClass eTypeClass ) noexcept
110 static typelib_TypeDescriptionReference * s_aTypes[] = {
111 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
112 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
113 nullptr, nullptr, nullptr };
115 if (! s_aTypes[eTypeClass])
117 MutexGuard aGuard( typelib_StaticInitMutex() );
118 if (! s_aTypes[eTypeClass])
120 static constexpr OUString s_aTypeNames[] = {
121 u"void"_ustr, u"char"_ustr, u"boolean"_ustr, u"byte"_ustr,
122 u"short"_ustr, u"unsigned short"_ustr, u"long"_ustr, u"unsigned long"_ustr,
123 u"hyper"_ustr, u"unsigned hyper"_ustr, u"float"_ustr, u"double"_ustr,
124 u"string"_ustr, u"type"_ustr, u"any"_ustr };
126 switch (eTypeClass)
128 case typelib_TypeClass_EXCEPTION:
129 case typelib_TypeClass_INTERFACE:
131 // type
132 if (! s_aTypes[typelib_TypeClass_TYPE])
134 OUString sTypeName(u"type"_ustr);
135 ::typelib_typedescriptionreference_new(
136 &s_aTypes[typelib_TypeClass_TYPE], typelib_TypeClass_TYPE, sTypeName.pData );
137 // another static ref:
138 ++s_aTypes[typelib_TypeClass_TYPE]->nStaticRefCount;
140 // any
141 if (! s_aTypes[typelib_TypeClass_ANY])
143 OUString sTypeName(u"any"_ustr);
144 ::typelib_typedescriptionreference_new(
145 &s_aTypes[typelib_TypeClass_ANY], typelib_TypeClass_ANY, sTypeName.pData );
146 // another static ref:
147 ++s_aTypes[typelib_TypeClass_ANY]->nStaticRefCount;
149 // string
150 if (! s_aTypes[typelib_TypeClass_STRING])
152 OUString sTypeName(u"string"_ustr);
153 ::typelib_typedescriptionreference_new(
154 &s_aTypes[typelib_TypeClass_STRING], typelib_TypeClass_STRING, sTypeName.pData );
155 // another static ref:
156 ++s_aTypes[typelib_TypeClass_STRING]->nStaticRefCount;
158 // XInterface
159 if (! s_aTypes[typelib_TypeClass_INTERFACE])
161 OUString sTypeName(u"com.sun.star.uno.XInterface"_ustr);
163 typelib_InterfaceTypeDescription * pTD = nullptr;
165 typelib_TypeDescriptionReference * pMembers[3] = { nullptr,nullptr,nullptr };
166 OUString sMethodName0(u"com.sun.star.uno.XInterface::queryInterface"_ustr);
167 ::typelib_typedescriptionreference_new(
168 &pMembers[0], typelib_TypeClass_INTERFACE_METHOD, sMethodName0.pData );
169 OUString sMethodName1(u"com.sun.star.uno.XInterface::acquire"_ustr);
170 ::typelib_typedescriptionreference_new(
171 &pMembers[1], typelib_TypeClass_INTERFACE_METHOD, sMethodName1.pData );
172 OUString sMethodName2(u"com.sun.star.uno.XInterface::release"_ustr);
173 ::typelib_typedescriptionreference_new(
174 &pMembers[2], typelib_TypeClass_INTERFACE_METHOD, sMethodName2.pData );
176 ::typelib_typedescription_newInterface(
177 &pTD, sTypeName.pData, 0, 0, 0, 0, 0, nullptr, 3, pMembers );
179 ::typelib_typedescription_register( reinterpret_cast<typelib_TypeDescription **>(&pTD) );
180 s_aTypes[typelib_TypeClass_INTERFACE] = pTD->aBase.pWeakRef;
181 ::typelib_typedescriptionreference_acquire(
182 s_aTypes[typelib_TypeClass_INTERFACE] );
183 // another static ref:
184 ++s_aTypes[typelib_TypeClass_INTERFACE]->nStaticRefCount;
185 ::typelib_typedescription_release( &pTD->aBase );
187 ::typelib_typedescriptionreference_release( pMembers[0] );
188 ::typelib_typedescriptionreference_release( pMembers[1] );
189 ::typelib_typedescriptionreference_release( pMembers[2] );
190 // Exception
191 assert( ! s_aTypes[typelib_TypeClass_EXCEPTION] );
193 typelib_TypeDescription * pTD1 = nullptr;
194 OUString sTypeName1(u"com.sun.star.uno.Exception"_ustr);
196 typelib_CompoundMember_Init aMembers[2];
197 OUString sMemberType0(u"string"_ustr);
198 OUString sMemberName0(u"Message"_ustr);
199 aMembers[0].eTypeClass = typelib_TypeClass_STRING;
200 aMembers[0].pTypeName = sMemberType0.pData;
201 aMembers[0].pMemberName = sMemberName0.pData;
202 OUString sMemberType1(u"com.sun.star.uno.XInterface"_ustr);
203 OUString sMemberName1(u"Context"_ustr);
204 aMembers[1].eTypeClass = typelib_TypeClass_INTERFACE;
205 aMembers[1].pTypeName = sMemberType1.pData;
206 aMembers[1].pMemberName = sMemberName1.pData;
208 ::typelib_typedescription_new(
209 &pTD1, typelib_TypeClass_EXCEPTION, sTypeName1.pData, nullptr, 2, aMembers );
210 typelib_typedescription_register( &pTD1 );
211 s_aTypes[typelib_TypeClass_EXCEPTION] = pTD1->pWeakRef;
212 typelib_typedescriptionreference_acquire(
213 s_aTypes[typelib_TypeClass_EXCEPTION]);
214 // another static ref:
215 ++s_aTypes[typelib_TypeClass_EXCEPTION]->nStaticRefCount;
216 // RuntimeException
217 OUString sTypeName2(u"com.sun.star.uno.RuntimeException"_ustr);
218 ::typelib_typedescription_new(
219 &pTD1, typelib_TypeClass_EXCEPTION, sTypeName2.pData, s_aTypes[typelib_TypeClass_EXCEPTION], 0, nullptr );
220 ::typelib_typedescription_register( &pTD1 );
221 ::typelib_typedescription_release( pTD1 );
223 // XInterface members
224 typelib_InterfaceMethodTypeDescription * pMethod = nullptr;
225 typelib_Parameter_Init aParameters[1];
226 OUString sParamName0(u"aType"_ustr);
227 OUString sParamType0(u"type"_ustr);
228 aParameters[0].pParamName = sParamName0.pData;
229 aParameters[0].eTypeClass = typelib_TypeClass_TYPE;
230 aParameters[0].pTypeName = sParamType0.pData;
231 aParameters[0].bIn = true;
232 aParameters[0].bOut = false;
233 rtl_uString * pExceptions[1];
234 OUString sExceptionName0(u"com.sun.star.uno.RuntimeException"_ustr);
235 pExceptions[0] = sExceptionName0.pData;
236 OUString sReturnType0(u"any"_ustr);
237 typelib_typedescription_newInterfaceMethod(
238 &pMethod, 0, false, sMethodName0.pData,
239 typelib_TypeClass_ANY, sReturnType0.pData,
240 1, aParameters, 1, pExceptions );
241 ::typelib_typedescription_register( reinterpret_cast<typelib_TypeDescription**>(&pMethod) );
243 OUString sReturnType1(u"void"_ustr);
244 ::typelib_typedescription_newInterfaceMethod(
245 &pMethod, 1, true, sMethodName1.pData,
246 typelib_TypeClass_VOID, sReturnType1.pData, 0, nullptr, 0, nullptr );
247 ::typelib_typedescription_register( reinterpret_cast<typelib_TypeDescription**>(&pMethod) );
249 ::typelib_typedescription_newInterfaceMethod(
250 &pMethod, 2, true, sMethodName2.pData,
251 typelib_TypeClass_VOID, sReturnType1.pData,
252 0, nullptr, 0, nullptr );
253 ::typelib_typedescription_register( reinterpret_cast<typelib_TypeDescription**>(&pMethod) );
254 ::typelib_typedescription_release( &pMethod->aBase.aBase );
256 break;
258 default:
260 OUString aTypeName( s_aTypeNames[eTypeClass] );
261 ::typelib_typedescriptionreference_new( &s_aTypes[eTypeClass], eTypeClass, aTypeName.pData );
262 // another static ref:
263 ++s_aTypes[eTypeClass]->nStaticRefCount;
268 return &s_aTypes[eTypeClass];
271 void SAL_CALL typelib_static_type_init(
272 typelib_TypeDescriptionReference ** ppRef,
273 typelib_TypeClass eTypeClass, const char * pTypeName ) noexcept
275 if (! *ppRef)
277 MutexGuard aGuard( typelib_StaticInitMutex() );
278 if (! *ppRef)
280 OUString aTypeName( OUString::createFromAscii( pTypeName ) );
281 ::typelib_typedescriptionreference_new( ppRef, eTypeClass, aTypeName.pData );
283 assert(*ppRef && "coverity[var_deref_op] - shouldn't be possible");
284 ++((*ppRef)->nStaticRefCount);
289 void SAL_CALL typelib_static_sequence_type_init(
290 typelib_TypeDescriptionReference ** ppRef,
291 typelib_TypeDescriptionReference * pElementType ) noexcept
293 if ( *ppRef)
294 return;
296 MutexGuard aGuard( typelib_StaticInitMutex() );
297 if ( *ppRef)
298 return;
300 OUString aTypeName = "[]" + OUString::unacquired(&pElementType->pTypeName);
302 static_assert( ! TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK(typelib_TypeClass_SEQUENCE) );
303 *ppRef = igetTypeByName( aTypeName.pData );
304 if (!*ppRef)
306 typelib_TypeDescription * pReg = nullptr;
307 ::typelib_typedescription_new(
308 &pReg, typelib_TypeClass_SEQUENCE,
309 aTypeName.pData, pElementType, 0, nullptr );
311 ::typelib_typedescription_register( &pReg );
312 *ppRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg);
313 assert( *ppRef == pReg->pWeakRef );
315 // another static ref:
316 ++((*ppRef)->nStaticRefCount);
320 namespace {
322 void init(
323 typelib_TypeDescriptionReference ** ppRef,
324 typelib_TypeClass eTypeClass, const char * pTypeName,
325 typelib_TypeDescriptionReference * pBaseType,
326 sal_Int32 nMembers, typelib_TypeDescriptionReference ** ppMembers,
327 sal_Bool const * pParameterizedTypes)
329 assert( eTypeClass == typelib_TypeClass_STRUCT || eTypeClass == typelib_TypeClass_EXCEPTION );
331 if ( *ppRef)
332 return;
334 MutexGuard aGuard( typelib_StaticInitMutex() );
335 if ( *ppRef)
336 return;
338 assert( ! TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK(eTypeClass) );
339 OUString aTypeName( OUString::createFromAscii( pTypeName ) );
340 *ppRef = igetTypeByName( aTypeName.pData );
341 if (!*ppRef)
343 typelib_CompoundTypeDescription * pComp = nullptr;
344 ::typelib_typedescription_newEmpty(
345 reinterpret_cast<typelib_TypeDescription **>(&pComp), eTypeClass, aTypeName.pData );
347 sal_Int32 nOffset = 0;
348 if (pBaseType)
350 ::typelib_typedescriptionreference_getDescription(
351 reinterpret_cast<typelib_TypeDescription **>(&pComp->pBaseTypeDescription), pBaseType );
352 assert( pComp->pBaseTypeDescription );
353 nOffset = pComp->pBaseTypeDescription->aBase.nSize;
354 assert( newAlignedSize( 0, pComp->pBaseTypeDescription->aBase.nSize, pComp->pBaseTypeDescription->aBase.nAlignment ) == pComp->pBaseTypeDescription->aBase.nSize ); // unexpected offset
357 if (nMembers)
359 pComp->nMembers = nMembers;
360 pComp->pMemberOffsets = new sal_Int32[ nMembers ];
361 pComp->ppTypeRefs = new typelib_TypeDescriptionReference *[ nMembers ];
362 if (pParameterizedTypes != nullptr) {
363 reinterpret_cast< typelib_StructTypeDescription * >(
364 pComp)->pParameterizedTypes
365 = new sal_Bool[nMembers];
367 for ( sal_Int32 i = 0 ; i < nMembers; ++i )
369 pComp->ppTypeRefs[i] = ppMembers[i];
370 ::typelib_typedescriptionreference_acquire(
371 pComp->ppTypeRefs[i] );
372 // write offset
373 typelib_TypeDescription * pTD = nullptr;
374 TYPELIB_DANGER_GET( &pTD, pComp->ppTypeRefs[i] );
375 assert( pTD->nSize ); // void member?
376 nOffset = newAlignedSize( nOffset, pTD->nSize, pTD->nAlignment );
377 pComp->pMemberOffsets[i] = nOffset - pTD->nSize;
378 TYPELIB_DANGER_RELEASE( pTD );
380 if (pParameterizedTypes != nullptr) {
381 reinterpret_cast< typelib_StructTypeDescription * >(
382 pComp)->pParameterizedTypes[i]
383 = pParameterizedTypes[i];
388 typelib_TypeDescription * pReg = &pComp->aBase;
389 pReg->pWeakRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg);
390 // sizeof(void) not allowed
391 pReg->nSize = ::typelib_typedescription_getAlignedUnoSize( pReg, 0, pReg->nAlignment );
392 pReg->nAlignment = adjustAlignment( pReg->nAlignment );
393 pReg->bComplete = false;
395 ::typelib_typedescription_register( &pReg );
396 *ppRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg);
397 assert( *ppRef == pReg->pWeakRef );
399 // another static ref:
400 ++((*ppRef)->nStaticRefCount);
405 void SAL_CALL typelib_static_compound_type_init(
406 typelib_TypeDescriptionReference ** ppRef,
407 typelib_TypeClass eTypeClass, const char * pTypeName,
408 typelib_TypeDescriptionReference * pBaseType,
409 sal_Int32 nMembers, typelib_TypeDescriptionReference ** ppMembers ) noexcept
411 init(ppRef, eTypeClass, pTypeName, pBaseType, nMembers, ppMembers, nullptr);
414 void SAL_CALL typelib_static_struct_type_init(
415 typelib_TypeDescriptionReference ** ppRef, const char * pTypeName,
416 typelib_TypeDescriptionReference * pBaseType,
417 sal_Int32 nMembers, typelib_TypeDescriptionReference ** ppMembers,
418 sal_Bool const * pParameterizedTypes ) noexcept
420 init(
421 ppRef, typelib_TypeClass_STRUCT, pTypeName, pBaseType, nMembers,
422 ppMembers, pParameterizedTypes);
425 void SAL_CALL typelib_static_interface_type_init(
426 typelib_TypeDescriptionReference ** ppRef,
427 const char * pTypeName,
428 typelib_TypeDescriptionReference * pBaseType ) noexcept
430 // coverity[callee_ptr_arith] - not a bug
431 typelib_static_mi_interface_type_init(
432 ppRef, pTypeName, pBaseType == nullptr ? 0 : 1, &pBaseType);
435 void SAL_CALL typelib_static_mi_interface_type_init(
436 typelib_TypeDescriptionReference ** ppRef,
437 const char * pTypeName,
438 sal_Int32 nBaseTypes,
439 typelib_TypeDescriptionReference ** ppBaseTypes ) noexcept
441 if ( *ppRef)
442 return;
444 MutexGuard aGuard( typelib_StaticInitMutex() );
445 if ( *ppRef)
446 return;
448 static_assert( ! TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK(typelib_TypeClass_INTERFACE) );
449 OUString aTypeName( OUString::createFromAscii( pTypeName ) );
450 *ppRef = igetTypeByName( aTypeName.pData );
451 if (!*ppRef)
453 typelib_InterfaceTypeDescription * pIface = nullptr;
454 ::typelib_typedescription_newEmpty(
455 reinterpret_cast<typelib_TypeDescription **>(&pIface), typelib_TypeClass_INTERFACE, aTypeName.pData );
457 pIface->nBaseTypes = std::max< sal_Int32 >(nBaseTypes, 1);
458 pIface->ppBaseTypes = new typelib_InterfaceTypeDescription *[
459 pIface->nBaseTypes];
460 if (nBaseTypes > 0)
462 for (sal_Int32 i = 0; i < nBaseTypes; ++i) {
463 pIface->ppBaseTypes[i] = nullptr;
464 ::typelib_typedescriptionreference_getDescription(
465 reinterpret_cast<typelib_TypeDescription **>(&pIface->ppBaseTypes[i]), ppBaseTypes[i] );
466 assert( pIface->ppBaseTypes[i] );
469 else
471 pIface->ppBaseTypes[0] = nullptr;
472 ::typelib_typedescriptionreference_getDescription(
473 reinterpret_cast<typelib_TypeDescription **>(&pIface->ppBaseTypes[0]),
474 * ::typelib_static_type_getByTypeClass( typelib_TypeClass_INTERFACE ) );
475 assert( pIface->ppBaseTypes[0] );
477 pIface->pBaseTypeDescription = pIface->ppBaseTypes[0];
478 typelib_typedescription_acquire(
479 &pIface->pBaseTypeDescription->aBase);
481 typelib_TypeDescription * pReg = &pIface->aBase;
482 pReg->pWeakRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg);
483 // sizeof(void) not allowed
484 pReg->nSize = ::typelib_typedescription_getAlignedUnoSize( pReg, 0, pReg->nAlignment );
486 pReg->nAlignment = adjustAlignment( pReg->nAlignment );
487 pReg->bComplete = false;
489 ::typelib_typedescription_register( &pReg );
490 *ppRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg);
491 assert( *ppRef == pReg->pWeakRef );
493 // another static ref:
494 ++((*ppRef)->nStaticRefCount);
498 void SAL_CALL typelib_static_enum_type_init(
499 typelib_TypeDescriptionReference ** ppRef,
500 const char * pTypeName,
501 sal_Int32 nDefaultValue ) noexcept
503 if ( *ppRef)
504 return;
506 MutexGuard aGuard( typelib_StaticInitMutex() );
507 if ( *ppRef)
508 return;
510 static_assert( ! TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK(typelib_TypeClass_ENUM) );
511 OUString aTypeName( OUString::createFromAscii( pTypeName ) );
512 *ppRef = igetTypeByName( aTypeName.pData );
513 if (!*ppRef)
515 typelib_TypeDescription * pReg = nullptr;
516 ::typelib_typedescription_newEmpty(
517 &pReg, typelib_TypeClass_ENUM, aTypeName.pData );
518 typelib_EnumTypeDescription * pEnum = reinterpret_cast<typelib_EnumTypeDescription *>(pReg);
520 pEnum->nDefaultEnumValue = nDefaultValue;
522 pReg->pWeakRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg);
523 // sizeof(void) not allowed
524 pReg->nSize = ::typelib_typedescription_getAlignedUnoSize( pReg, 0, pReg->nAlignment );
525 pReg->nAlignment = ::adjustAlignment( pReg->nAlignment );
526 pReg->bComplete = false;
528 ::typelib_typedescription_register( &pReg );
529 *ppRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg);
530 assert( *ppRef == pReg->pWeakRef );
532 // another static ref:
533 ++((*ppRef)->nStaticRefCount);
536 } // extern "C"
540 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */