Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/cppuhelper/source/implbase_ex.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
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/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
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 .
18
 */
19
20
#include <osl/diagnose.h>
21
#include <sal/log.hxx>
22
#include <cppuhelper/compbase_ex.hxx>
23
#include <cppuhelper/implbase_ex.hxx>
24
25
#include "type_entries.hxx"
26
27
#include <com/sun/star/uno/RuntimeException.hpp>
28
29
#include <mutex>
30
31
using namespace ::cppu;
32
using namespace ::com::sun::star;
33
using namespace ::com::sun::star::uno;
34
35
namespace cppu
36
{
37
38
static void checkInterface( Type const & rType )
39
274M
{
40
274M
    if (TypeClass_INTERFACE != rType.getTypeClass())
41
0
    {
42
0
        OUString msg( "querying for interface \"" + rType.getTypeName() + "\": no interface type!" );
43
0
        SAL_WARN( "cppuhelper", msg );
44
0
        throw RuntimeException( msg );
45
0
    }
46
274M
}
47
48
static bool isXInterface( rtl_uString * pStr )
49
254M
{
50
254M
    return OUString::unacquired(&pStr) == "com.sun.star.uno.XInterface";
51
254M
}
52
53
static void * makeInterface( sal_IntPtr nOffset, void * that )
54
109M
{
55
109M
    return (static_cast<char *>(that) + nOffset);
56
109M
}
57
58
static bool td_equals(
59
    typelib_TypeDescriptionReference const * pTDR1,
60
    typelib_TypeDescriptionReference const * pTDR2 )
61
2.13G
{
62
2.13G
    return ((pTDR1 == pTDR2) ||
63
2.03G
            OUString::unacquired(&pTDR1->pTypeName) == OUString::unacquired(&pTDR2->pTypeName));
64
2.13G
}
65
66
type_entry * getTypeEntries( class_data * cd )
67
177M
{
68
177M
    type_entry * pEntries = cd->m_typeEntries;
69
177M
    if (! cd->m_storedTypeRefs) // not inited?
70
1.61k
    {
71
1.61k
        static std::mutex aMutex;
72
1.61k
        std::scoped_lock guard( aMutex );
73
1.61k
        if (! cd->m_storedTypeRefs) // not inited?
74
1.61k
        {
75
            // get all types
76
9.68k
            for ( sal_Int32 n = cd->m_nTypes; n--; )
77
8.07k
            {
78
8.07k
                type_entry * pEntry = &pEntries[ n ];
79
8.07k
                Type const & rType = (*pEntry->m_type.getCppuType)( nullptr );
80
8.07k
                OSL_ENSURE( rType.getTypeClass() == TypeClass_INTERFACE, "### wrong helper init: expected interface!" );
81
8.07k
                OSL_ENSURE( ! isXInterface( rType.getTypeLibType()->pTypeName ), "### want to implement XInterface: template argument is XInterface?!?!?!" );
82
8.07k
                if (rType.getTypeClass() != TypeClass_INTERFACE)
83
0
                {
84
0
                    OUString msg( "type \"" + rType.getTypeName() + "\" is no interface type!" );
85
0
                    SAL_WARN( "cppuhelper", msg );
86
0
                    throw RuntimeException( msg );
87
0
                }
88
                // ref is statically held by getCppuType()
89
8.07k
                pEntry->m_type.typeRef = rType.getTypeLibType();
90
8.07k
            }
91
1.61k
            OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
92
1.61k
            cd->m_storedTypeRefs = true;
93
1.61k
        }
94
1.61k
    }
95
177M
    else
96
177M
    {
97
177M
        OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
98
177M
    }
99
177M
    return pEntries;
100
177M
}
101
102
static void fillTypes( Type * types, class_data * cd )
103
15
{
104
15
    type_entry * pEntries = getTypeEntries( cd );
105
110
    for ( sal_Int32 n = cd->m_nTypes; n--; )
106
95
    {
107
95
        types[ n ] = pEntries[ n ].m_type.typeRef;
108
95
    }
109
15
}
110
111
namespace {
112
113
bool recursivelyFindType(
114
    typelib_TypeDescriptionReference const * demandedType,
115
    typelib_InterfaceTypeDescription const * type, sal_IntPtr * offset)
116
1.21G
{
117
    // This code assumes that the vtables of a multiple-inheritance class (the
118
    // offset amount by which to adjust the this pointer) follow one another in
119
    // the object layout, and that they contain slots for the inherited classes
120
    // in a specific order.  In theory, that need not hold for any given
121
    // platform; in practice, it seems to work well on all supported platforms:
122
1.53G
 next:
123
2.95G
    for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) {
124
1.80G
        if (i > 0) {
125
268M
            *offset += sizeof (void *);
126
268M
        }
127
1.80G
        typelib_InterfaceTypeDescription const * base = type->ppBaseTypes[i];
128
        // ignore XInterface:
129
1.80G
        if (base->nBaseTypes > 0) {
130
713M
            if (td_equals(
131
713M
                    reinterpret_cast<
132
713M
                        typelib_TypeDescriptionReference const * >(base),
133
713M
                    demandedType))
134
33.3M
            {
135
33.3M
                return true;
136
33.3M
            }
137
            // Profiling showed that it is important to speed up the common case
138
            // of only one base:
139
679M
            if (type->nBaseTypes == 1) {
140
321M
                type = base;
141
321M
                goto next;
142
321M
            }
143
358M
            if (recursivelyFindType(demandedType, base, offset)) {
144
29.4M
                return true;
145
29.4M
            }
146
358M
        }
147
1.80G
    }
148
1.15G
    return false;
149
1.53G
}
150
151
}
152
153
static void * queryDeepNoXInterface(
154
    typelib_TypeDescriptionReference const * pDemandedTDR, class_data * cd, void * that )
155
177M
{
156
177M
    type_entry * pEntries = getTypeEntries( cd );
157
177M
    sal_Int32 nTypes = cd->m_nTypes;
158
177M
    sal_Int32 n;
159
160
    // try top interfaces without getting td
161
1.53G
    for ( n = 0; n < nTypes; ++n )
162
1.41G
    {
163
1.41G
        if (td_equals( pEntries[ n ].m_type.typeRef, pDemandedTDR ))
164
65.1M
        {
165
65.1M
            return makeInterface( pEntries[ n ].m_offset, that );
166
65.1M
        }
167
1.41G
    }
168
    // query deep getting td
169
935M
    for ( n = 0; n < nTypes; ++n )
170
856M
    {
171
856M
        typelib_TypeDescription * pTD = nullptr;
172
856M
        TYPELIB_DANGER_GET( &pTD, pEntries[ n ].m_type.typeRef );
173
856M
        if (pTD)
174
856M
        {
175
            // exclude top (already tested) and bottom (XInterface) interface
176
856M
            OSL_ENSURE(
177
856M
                reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD)->
178
856M
                    nBaseTypes > 0,
179
856M
                "### want to implement XInterface:"
180
856M
                    " template argument is XInterface?!?!?!" );
181
856M
            sal_IntPtr offset = pEntries[n].m_offset;
182
856M
            bool found = recursivelyFindType(
183
856M
                pDemandedTDR,
184
856M
                reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD),
185
856M
                &offset);
186
856M
            TYPELIB_DANGER_RELEASE( pTD );
187
856M
            if (found) {
188
33.3M
                return makeInterface( offset, that );
189
33.3M
            }
190
856M
        }
191
0
        else
192
0
        {
193
0
            OUString msg( "cannot get type description for type \"" + OUString::unacquired(&pEntries[ n ].m_type.typeRef->pTypeName) + "\"!" );
194
0
            SAL_WARN( "cppuhelper", msg );
195
0
            throw RuntimeException( msg );
196
0
        }
197
856M
    }
198
79.0M
    return nullptr;
199
112M
}
200
201
// ImplHelper
202
203
Any SAL_CALL ImplHelper_query(
204
    Type const & rType, class_data * cd, void * that )
205
15.7M
{
206
15.7M
    checkInterface( rType );
207
15.7M
    typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
208
209
15.7M
    void * p;
210
    // shortcut for XInterface
211
15.7M
    if (isXInterface( pTDR->pTypeName ))
212
10.7M
    {
213
        // take first one
214
10.7M
        p = makeInterface( cd->m_typeEntries[ 0 ].m_offset, that );
215
10.7M
    }
216
5.02M
    else
217
5.02M
    {
218
5.02M
        p = queryDeepNoXInterface( pTDR, cd, that );
219
5.02M
        if (! p)
220
4.81M
        {
221
4.81M
            return Any();
222
4.81M
        }
223
5.02M
    }
224
10.9M
    return Any( &p, pTDR );
225
15.7M
}
226
227
Any SAL_CALL ImplHelper_queryNoXInterface(
228
    Type const & rType, class_data * cd, void * that )
229
20.0M
{
230
20.0M
    checkInterface( rType );
231
20.0M
    typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
232
233
20.0M
    void * p = queryDeepNoXInterface( pTDR, cd, that );
234
20.0M
    if (p)
235
14.1M
    {
236
14.1M
        return Any( &p, pTDR );
237
14.1M
    }
238
5.99M
    return Any();
239
20.0M
}
240
241
css::uno::Sequence<sal_Int8> ImplHelper_getImplementationId(
242
    SAL_UNUSED_PARAMETER class_data *)
243
0
{
244
0
    return css::uno::Sequence<sal_Int8>();
245
0
}
246
247
Sequence< Type > SAL_CALL ImplHelper_getTypes(
248
    class_data * cd )
249
0
{
250
0
    Sequence< Type > types( cd->m_nTypes );
251
0
    Type * pTypes = types.getArray();
252
0
    fillTypes( pTypes, cd );
253
0
    return types;
254
0
}
255
256
Sequence< Type >  SAL_CALL ImplInhHelper_getTypes(
257
    class_data * cd, Sequence< Type > const & rAddTypes )
258
0
{
259
0
    sal_Int32 nImplTypes = cd->m_nTypes;
260
0
    Sequence<Type> types(nImplTypes + rAddTypes.getLength());
261
0
    Type * pTypes = types.getArray();
262
0
    fillTypes( pTypes, cd );
263
    // append base types
264
0
    std::copy(rAddTypes.begin(), rAddTypes.end(), pTypes + nImplTypes);
265
0
    return types;
266
0
}
267
268
// WeakImplHelper
269
270
Any SAL_CALL WeakImplHelper_query(
271
    Type const & rType, class_data * cd, void * that, OWeakObject * pBase )
272
54.3M
{
273
54.3M
    checkInterface( rType );
274
54.3M
    typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
275
276
    // shortcut XInterface to OWeakObject
277
54.3M
    if (! isXInterface( pTDR->pTypeName ))
278
52.9M
    {
279
52.9M
        void * p = queryDeepNoXInterface( pTDR, cd, that );
280
52.9M
        if (p)
281
33.9M
        {
282
33.9M
            return Any( &p, pTDR );
283
33.9M
        }
284
52.9M
    }
285
20.3M
    return pBase->OWeakObject::queryInterface( rType );
286
54.3M
}
287
288
Sequence< Type > SAL_CALL WeakImplHelper_getTypes(
289
    class_data * cd )
290
10
{
291
10
    sal_Int32 nTypes = cd->m_nTypes;
292
10
    Sequence< Type > types( nTypes +1 );
293
10
    Type * pTypes = types.getArray();
294
10
    fillTypes( pTypes, cd );
295
10
    pTypes[ nTypes ] = cppu::UnoType<XWeak>::get();
296
10
    return types;
297
10
}
298
299
// WeakAggImplHelper
300
301
Any SAL_CALL WeakAggImplHelper_queryAgg(
302
    Type const & rType, class_data * cd, void * that, OWeakAggObject * pBase )
303
5.81M
{
304
5.81M
    checkInterface( rType );
305
5.81M
    typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
306
307
    // shortcut XInterface to OWeakAggObject
308
5.81M
    if (! isXInterface( pTDR->pTypeName ))
309
4.95M
    {
310
4.95M
        void * p = queryDeepNoXInterface( pTDR, cd, that );
311
4.95M
        if (p)
312
4.05M
        {
313
4.05M
            return Any( &p, pTDR );
314
4.05M
        }
315
4.95M
    }
316
1.76M
    return pBase->OWeakAggObject::queryAggregation( rType );
317
5.81M
}
318
319
Sequence< Type > SAL_CALL WeakAggImplHelper_getTypes(
320
    class_data * cd )
321
0
{
322
0
    sal_Int32 nTypes = cd->m_nTypes;
323
0
    Sequence< Type > types( nTypes +2 );
324
0
    Type * pTypes = types.getArray();
325
0
    fillTypes( pTypes, cd );
326
0
    pTypes[ nTypes++ ] = cppu::UnoType<XWeak>::get();
327
0
    pTypes[ nTypes ] = cppu::UnoType<XAggregation>::get();
328
0
    return types;
329
0
}
330
331
// WeakComponentImplHelper
332
333
Any SAL_CALL WeakComponentImplHelper_query(
334
    Type const & rType, class_data * cd, void * that, WeakComponentImplHelperBase * pBase )
335
178M
{
336
178M
    checkInterface( rType );
337
178M
    typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
338
339
    // shortcut XInterface to WeakComponentImplHelperBase
340
178M
    if (! isXInterface( pTDR->pTypeName ))
341
94.4M
    {
342
94.4M
        void * p = queryDeepNoXInterface( pTDR, cd, that );
343
94.4M
        if (p)
344
46.1M
        {
345
46.1M
            return Any( &p, pTDR );
346
46.1M
        }
347
94.4M
    }
348
132M
    return pBase->WeakComponentImplHelperBase::queryInterface( rType );
349
178M
}
350
351
Sequence< Type > SAL_CALL WeakComponentImplHelper_getTypes(
352
    class_data * cd )
353
5
{
354
5
    sal_Int32 nTypes = cd->m_nTypes;
355
5
    Sequence< Type > types( nTypes +2 );
356
5
    Type * pTypes = types.getArray();
357
5
    fillTypes( pTypes, cd );
358
5
    pTypes[ nTypes++ ] = cppu::UnoType<XWeak>::get();
359
5
    pTypes[ nTypes ] = cppu::UnoType<lang::XComponent>::get();
360
5
    return types;
361
5
}
362
363
// WeakAggComponentImplHelper
364
365
Any SAL_CALL WeakAggComponentImplHelper_queryAgg(
366
    Type const & rType, class_data * cd, void * that, WeakAggComponentImplHelperBase * pBase )
367
117k
{
368
117k
    checkInterface( rType );
369
117k
    typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
370
371
    // shortcut XInterface to WeakAggComponentImplHelperBase
372
117k
    if (! isXInterface( pTDR->pTypeName ))
373
117k
    {
374
117k
        void * p = queryDeepNoXInterface( pTDR, cd, that );
375
117k
        if (p)
376
21.3k
        {
377
21.3k
            return Any( &p, pTDR );
378
21.3k
        }
379
117k
    }
380
95.9k
    return pBase->WeakAggComponentImplHelperBase::queryAggregation( rType );
381
117k
}
382
383
Sequence< Type > SAL_CALL WeakAggComponentImplHelper_getTypes(
384
    class_data * cd )
385
0
{
386
0
    sal_Int32 nTypes = cd->m_nTypes;
387
0
    Sequence< Type > types( nTypes +3 );
388
0
    Type * pTypes = types.getArray();
389
0
    fillTypes( pTypes, cd );
390
0
    pTypes[ nTypes++ ] = cppu::UnoType<XWeak>::get();
391
0
    pTypes[ nTypes++ ] = cppu::UnoType<XAggregation>::get();
392
0
    pTypes[ nTypes ] = cppu::UnoType<lang::XComponent>::get();
393
0
    return types;
394
0
}
395
396
}
397
398
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */