Coverage Report

Created: 2026-02-14 09:37

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
206M
{
40
206M
    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
206M
}
47
48
static bool isXInterface( rtl_uString * pStr )
49
187M
{
50
187M
    return OUString::unacquired(&pStr) == "com.sun.star.uno.XInterface";
51
187M
}
52
53
static void * makeInterface( sal_IntPtr nOffset, void * that )
54
84.3M
{
55
84.3M
    return (static_cast<char *>(that) + nOffset);
56
84.3M
}
57
58
static bool td_equals(
59
    typelib_TypeDescriptionReference const * pTDR1,
60
    typelib_TypeDescriptionReference const * pTDR2 )
61
1.52G
{
62
1.52G
    return ((pTDR1 == pTDR2) ||
63
1.45G
            OUString::unacquired(&pTDR1->pTypeName) == OUString::unacquired(&pTDR2->pTypeName));
64
1.52G
}
65
66
type_entry * getTypeEntries( class_data * cd )
67
133M
{
68
133M
    type_entry * pEntries = cd->m_typeEntries;
69
133M
    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.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.61k
            OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
92
1.61k
            cd->m_storedTypeRefs = true;
93
1.61k
        }
94
1.61k
    }
95
133M
    else
96
133M
    {
97
133M
        OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
98
133M
    }
99
133M
    return pEntries;
100
133M
}
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
869M
{
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.09G
 next:
123
2.10G
    for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) {
124
1.28G
        if (i > 0) {
125
184M
            *offset += sizeof (void *);
126
184M
        }
127
1.28G
        typelib_InterfaceTypeDescription const * base = type->ppBaseTypes[i];
128
        // ignore XInterface:
129
1.28G
        if (base->nBaseTypes > 0) {
130
496M
            if (td_equals(
131
496M
                    reinterpret_cast<
132
496M
                        typelib_TypeDescriptionReference const * >(base),
133
496M
                    demandedType))
134
23.2M
            {
135
23.2M
                return true;
136
23.2M
            }
137
            // Profiling showed that it is important to speed up the common case
138
            // of only one base:
139
473M
            if (type->nBaseTypes == 1) {
140
226M
                type = base;
141
226M
                goto next;
142
226M
            }
143
246M
            if (recursivelyFindType(demandedType, base, offset)) {
144
20.2M
                return true;
145
20.2M
            }
146
246M
        }
147
1.28G
    }
148
825M
    return false;
149
1.09G
}
150
151
}
152
153
static void * queryDeepNoXInterface(
154
    typelib_TypeDescriptionReference const * pDemandedTDR, class_data * cd, void * that )
155
133M
{
156
133M
    type_entry * pEntries = getTypeEntries( cd );
157
133M
    sal_Int32 nTypes = cd->m_nTypes;
158
133M
    sal_Int32 n;
159
160
    // try top interfaces without getting td
161
1.11G
    for ( n = 0; n < nTypes; ++n )
162
1.03G
    {
163
1.03G
        if (td_equals( pEntries[ n ].m_type.typeRef, pDemandedTDR ))
164
51.8M
        {
165
51.8M
            return makeInterface( pEntries[ n ].m_offset, that );
166
51.8M
        }
167
1.03G
    }
168
    // query deep getting td
169
680M
    for ( n = 0; n < nTypes; ++n )
170
622M
    {
171
622M
        typelib_TypeDescription * pTD = nullptr;
172
622M
        TYPELIB_DANGER_GET( &pTD, pEntries[ n ].m_type.typeRef );
173
622M
        if (pTD)
174
622M
        {
175
            // exclude top (already tested) and bottom (XInterface) interface
176
622M
            OSL_ENSURE(
177
622M
                reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD)->
178
622M
                    nBaseTypes > 0,
179
622M
                "### want to implement XInterface:"
180
622M
                    " template argument is XInterface?!?!?!" );
181
622M
            sal_IntPtr offset = pEntries[n].m_offset;
182
622M
            bool found = recursivelyFindType(
183
622M
                pDemandedTDR,
184
622M
                reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD),
185
622M
                &offset);
186
622M
            TYPELIB_DANGER_RELEASE( pTD );
187
622M
            if (found) {
188
23.2M
                return makeInterface( offset, that );
189
23.2M
            }
190
622M
        }
191
2
        else
192
2
        {
193
2
            OUString msg( "cannot get type description for type \"" + OUString::unacquired(&pEntries[ n ].m_type.typeRef->pTypeName) + "\"!" );
194
2
            SAL_WARN( "cppuhelper", msg );
195
2
            throw RuntimeException( msg );
196
2
        }
197
622M
    }
198
58.4M
    return nullptr;
199
81.7M
}
200
201
// ImplHelper
202
203
Any SAL_CALL ImplHelper_query(
204
    Type const & rType, class_data * cd, void * that )
205
13.6M
{
206
13.6M
    checkInterface( rType );
207
13.6M
    typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
208
209
13.6M
    void * p;
210
    // shortcut for XInterface
211
13.6M
    if (isXInterface( pTDR->pTypeName ))
212
9.22M
    {
213
        // take first one
214
9.22M
        p = makeInterface( cd->m_typeEntries[ 0 ].m_offset, that );
215
9.22M
    }
216
4.47M
    else
217
4.47M
    {
218
4.47M
        p = queryDeepNoXInterface( pTDR, cd, that );
219
4.47M
        if (! p)
220
4.28M
        {
221
4.28M
            return Any();
222
4.28M
        }
223
4.47M
    }
224
9.41M
    return Any( &p, pTDR );
225
13.6M
}
226
227
Any SAL_CALL ImplHelper_queryNoXInterface(
228
    Type const & rType, class_data * cd, void * that )
229
18.1M
{
230
18.1M
    checkInterface( rType );
231
18.1M
    typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
232
233
18.1M
    void * p = queryDeepNoXInterface( pTDR, cd, that );
234
18.1M
    if (p)
235
12.6M
    {
236
12.6M
        return Any( &p, pTDR );
237
12.6M
    }
238
5.48M
    return Any();
239
18.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
41.8M
{
273
41.8M
    checkInterface( rType );
274
41.8M
    typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
275
276
    // shortcut XInterface to OWeakObject
277
41.8M
    if (! isXInterface( pTDR->pTypeName ))
278
40.4M
    {
279
40.4M
        void * p = queryDeepNoXInterface( pTDR, cd, that );
280
40.4M
        if (p)
281
26.6M
        {
282
26.6M
            return Any( &p, pTDR );
283
26.6M
        }
284
40.4M
    }
285
15.1M
    return pBase->OWeakObject::queryInterface( rType );
286
41.8M
}
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
4.99M
{
304
4.99M
    checkInterface( rType );
305
4.99M
    typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
306
307
    // shortcut XInterface to OWeakAggObject
308
4.99M
    if (! isXInterface( pTDR->pTypeName ))
309
4.25M
    {
310
4.25M
        void * p = queryDeepNoXInterface( pTDR, cd, that );
311
4.25M
        if (p)
312
3.46M
        {
313
3.46M
            return Any( &p, pTDR );
314
3.46M
        }
315
4.25M
    }
316
1.52M
    return pBase->OWeakAggObject::queryAggregation( rType );
317
4.99M
}
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
127M
{
336
127M
    checkInterface( rType );
337
127M
    typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
338
339
    // shortcut XInterface to WeakComponentImplHelperBase
340
127M
    if (! isXInterface( pTDR->pTypeName ))
341
66.1M
    {
342
66.1M
        void * p = queryDeepNoXInterface( pTDR, cd, that );
343
66.1M
        if (p)
344
32.1M
        {
345
32.1M
            return Any( &p, pTDR );
346
32.1M
        }
347
66.1M
    }
348
95.2M
    return pBase->WeakComponentImplHelperBase::queryInterface( rType );
349
127M
}
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
107k
{
368
107k
    checkInterface( rType );
369
107k
    typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
370
371
    // shortcut XInterface to WeakAggComponentImplHelperBase
372
107k
    if (! isXInterface( pTDR->pTypeName ))
373
107k
    {
374
107k
        void * p = queryDeepNoXInterface( pTDR, cd, that );
375
107k
        if (p)
376
19.4k
        {
377
19.4k
            return Any( &p, pTDR );
378
19.4k
        }
379
107k
    }
380
87.6k
    return pBase->WeakAggComponentImplHelperBase::queryAggregation( rType );
381
107k
}
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: */