Coverage Report

Created: 2025-12-08 09:28

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
248M
{
40
248M
    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
248M
}
47
48
static bool isXInterface( rtl_uString * pStr )
49
223M
{
50
223M
    return OUString::unacquired(&pStr) == "com.sun.star.uno.XInterface";
51
223M
}
52
53
static void * makeInterface( sal_IntPtr nOffset, void * that )
54
105M
{
55
105M
    return (static_cast<char *>(that) + nOffset);
56
105M
}
57
58
static bool td_equals(
59
    typelib_TypeDescriptionReference const * pTDR1,
60
    typelib_TypeDescriptionReference const * pTDR2 )
61
1.88G
{
62
1.88G
    return ((pTDR1 == pTDR2) ||
63
1.78G
            OUString::unacquired(&pTDR1->pTypeName) == OUString::unacquired(&pTDR2->pTypeName));
64
1.88G
}
65
66
type_entry * getTypeEntries( class_data * cd )
67
166M
{
68
166M
    type_entry * pEntries = cd->m_typeEntries;
69
166M
    if (! cd->m_storedTypeRefs) // not inited?
70
1.60k
    {
71
1.60k
        static std::mutex aMutex;
72
1.60k
        std::scoped_lock guard( aMutex );
73
1.60k
        if (! cd->m_storedTypeRefs) // not inited?
74
1.60k
        {
75
            // get all types
76
9.71k
            for ( sal_Int32 n = cd->m_nTypes; n--; )
77
8.10k
            {
78
8.10k
                type_entry * pEntry = &pEntries[ n ];
79
8.10k
                Type const & rType = (*pEntry->m_type.getCppuType)( nullptr );
80
8.10k
                OSL_ENSURE( rType.getTypeClass() == TypeClass_INTERFACE, "### wrong helper init: expected interface!" );
81
8.10k
                OSL_ENSURE( ! isXInterface( rType.getTypeLibType()->pTypeName ), "### want to implement XInterface: template argument is XInterface?!?!?!" );
82
8.10k
                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.10k
                pEntry->m_type.typeRef = rType.getTypeLibType();
90
8.10k
            }
91
1.60k
            OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
92
1.60k
            cd->m_storedTypeRefs = true;
93
1.60k
        }
94
1.60k
    }
95
166M
    else
96
166M
    {
97
166M
        OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
98
166M
    }
99
166M
    return pEntries;
100
166M
}
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.06G
{
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.33G
 next:
123
2.57G
    for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) {
124
1.56G
        if (i > 0) {
125
224M
            *offset += sizeof (void *);
126
224M
        }
127
1.56G
        typelib_InterfaceTypeDescription const * base = type->ppBaseTypes[i];
128
        // ignore XInterface:
129
1.56G
        if (base->nBaseTypes > 0) {
130
604M
            if (td_equals(
131
604M
                    reinterpret_cast<
132
604M
                        typelib_TypeDescriptionReference const * >(base),
133
604M
                    demandedType))
134
28.9M
            {
135
28.9M
                return true;
136
28.9M
            }
137
            // Profiling showed that it is important to speed up the common case
138
            // of only one base:
139
575M
            if (type->nBaseTypes == 1) {
140
275M
                type = base;
141
275M
                goto next;
142
275M
            }
143
299M
            if (recursivelyFindType(demandedType, base, offset)) {
144
24.4M
                return true;
145
24.4M
            }
146
299M
        }
147
1.56G
    }
148
1.01G
    return false;
149
1.33G
}
150
151
}
152
153
static void * queryDeepNoXInterface(
154
    typelib_TypeDescriptionReference const * pDemandedTDR, class_data * cd, void * that )
155
166M
{
156
166M
    type_entry * pEntries = getTypeEntries( cd );
157
166M
    sal_Int32 nTypes = cd->m_nTypes;
158
166M
    sal_Int32 n;
159
160
    // try top interfaces without getting td
161
1.37G
    for ( n = 0; n < nTypes; ++n )
162
1.27G
    {
163
1.27G
        if (td_equals( pEntries[ n ].m_type.typeRef, pDemandedTDR ))
164
66.6M
        {
165
66.6M
            return makeInterface( pEntries[ n ].m_offset, that );
166
66.6M
        }
167
1.27G
    }
168
    // query deep getting td
169
834M
    for ( n = 0; n < nTypes; ++n )
170
763M
    {
171
763M
        typelib_TypeDescription * pTD = nullptr;
172
763M
        TYPELIB_DANGER_GET( &pTD, pEntries[ n ].m_type.typeRef );
173
763M
        if (pTD)
174
763M
        {
175
            // exclude top (already tested) and bottom (XInterface) interface
176
763M
            OSL_ENSURE(
177
763M
                reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD)->
178
763M
                    nBaseTypes > 0,
179
763M
                "### want to implement XInterface:"
180
763M
                    " template argument is XInterface?!?!?!" );
181
763M
            sal_IntPtr offset = pEntries[n].m_offset;
182
763M
            bool found = recursivelyFindType(
183
763M
                pDemandedTDR,
184
763M
                reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD),
185
763M
                &offset);
186
763M
            TYPELIB_DANGER_RELEASE( pTD );
187
763M
            if (found) {
188
28.9M
                return makeInterface( offset, that );
189
28.9M
            }
190
763M
        }
191
18.4E
        else
192
18.4E
        {
193
18.4E
            OUString msg( "cannot get type description for type \"" + OUString::unacquired(&pEntries[ n ].m_type.typeRef->pTypeName) + "\"!" );
194
18.4E
            SAL_WARN( "cppuhelper", msg );
195
18.4E
            throw RuntimeException( msg );
196
18.4E
        }
197
763M
    }
198
70.3M
    return nullptr;
199
99.3M
}
200
201
// ImplHelper
202
203
Any SAL_CALL ImplHelper_query(
204
    Type const & rType, class_data * cd, void * that )
205
13.8M
{
206
13.8M
    checkInterface( rType );
207
13.8M
    typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
208
209
13.8M
    void * p;
210
    // shortcut for XInterface
211
13.8M
    if (isXInterface( pTDR->pTypeName ))
212
9.43M
    {
213
        // take first one
214
9.43M
        p = makeInterface( cd->m_typeEntries[ 0 ].m_offset, that );
215
9.43M
    }
216
4.44M
    else
217
4.44M
    {
218
4.44M
        p = queryDeepNoXInterface( pTDR, cd, that );
219
4.44M
        if (! p)
220
4.26M
        {
221
4.26M
            return Any();
222
4.26M
        }
223
4.44M
    }
224
9.61M
    return Any( &p, pTDR );
225
13.8M
}
226
227
Any SAL_CALL ImplHelper_queryNoXInterface(
228
    Type const & rType, class_data * cd, void * that )
229
25.1M
{
230
25.1M
    checkInterface( rType );
231
25.1M
    typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
232
233
25.1M
    void * p = queryDeepNoXInterface( pTDR, cd, that );
234
25.1M
    if (p)
235
17.9M
    {
236
17.9M
        return Any( &p, pTDR );
237
17.9M
    }
238
7.24M
    return Any();
239
25.1M
}
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
53.7M
{
273
53.7M
    checkInterface( rType );
274
53.7M
    typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
275
276
    // shortcut XInterface to OWeakObject
277
53.7M
    if (! isXInterface( pTDR->pTypeName ))
278
52.0M
    {
279
52.0M
        void * p = queryDeepNoXInterface( pTDR, cd, that );
280
52.0M
        if (p)
281
34.5M
        {
282
34.5M
            return Any( &p, pTDR );
283
34.5M
        }
284
52.0M
    }
285
19.1M
    return pBase->OWeakObject::queryInterface( rType );
286
53.7M
}
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
6.48M
{
304
6.48M
    checkInterface( rType );
305
6.48M
    typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
306
307
    // shortcut XInterface to OWeakAggObject
308
6.48M
    if (! isXInterface( pTDR->pTypeName ))
309
5.48M
    {
310
5.48M
        void * p = queryDeepNoXInterface( pTDR, cd, that );
311
5.48M
        if (p)
312
4.45M
        {
313
4.45M
            return Any( &p, pTDR );
314
4.45M
        }
315
5.48M
    }
316
2.02M
    return pBase->OWeakAggObject::queryAggregation( rType );
317
6.48M
}
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
149M
{
336
149M
    checkInterface( rType );
337
149M
    typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
338
339
    // shortcut XInterface to WeakComponentImplHelperBase
340
149M
    if (! isXInterface( pTDR->pTypeName ))
341
78.7M
    {
342
78.7M
        void * p = queryDeepNoXInterface( pTDR, cd, that );
343
78.7M
        if (p)
344
38.4M
        {
345
38.4M
            return Any( &p, pTDR );
346
38.4M
        }
347
78.7M
    }
348
110M
    return pBase->WeakComponentImplHelperBase::queryInterface( rType );
349
149M
}
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
100k
{
368
100k
    checkInterface( rType );
369
100k
    typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
370
371
    // shortcut XInterface to WeakAggComponentImplHelperBase
372
100k
    if (! isXInterface( pTDR->pTypeName ))
373
100k
    {
374
100k
        void * p = queryDeepNoXInterface( pTDR, cd, that );
375
100k
        if (p)
376
18.3k
        {
377
18.3k
            return Any( &p, pTDR );
378
18.3k
        }
379
100k
    }
380
82.4k
    return pBase->WeakAggComponentImplHelperBase::queryAggregation( rType );
381
100k
}
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: */