Coverage Report

Created: 2026-11-06 11:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/cppuhelper/source/compbase.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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
10
#include <compbase2.hxx>
11
#include <cppuhelper/queryinterface.hxx>
12
#include <sal/log.hxx>
13
#include <osl/diagnose.h>
14
15
#include "type_entries.hxx"
16
17
namespace cppuhelper
18
{
19
0
WeakComponentImplHelperBase2::~WeakComponentImplHelperBase2() {}
20
21
// css::lang::XComponent
22
void SAL_CALL WeakComponentImplHelperBase2::dispose()
23
0
{
24
0
    std::unique_lock aGuard(m_aMutex);
25
0
    if (m_bDisposed)
26
0
        return;
27
0
    m_bDisposed = true;
28
0
    disposing(aGuard);
29
0
    if (!aGuard.owns_lock())
30
0
        aGuard.lock();
31
0
    css::lang::EventObject aEvt(static_cast<OWeakObject*>(this));
32
0
    maEventListeners.disposeAndClear(aGuard, aEvt);
33
0
}
34
35
0
void WeakComponentImplHelperBase2::disposing(std::unique_lock<std::mutex>&) {}
36
37
void SAL_CALL WeakComponentImplHelperBase2::addEventListener(
38
    css::uno::Reference<css::lang::XEventListener> const& rxListener)
39
109
{
40
109
    std::unique_lock aGuard(m_aMutex);
41
109
    if (m_bDisposed)
42
0
        return;
43
109
    maEventListeners.addInterface(aGuard, rxListener);
44
109
}
45
46
void SAL_CALL WeakComponentImplHelperBase2::removeEventListener(
47
    css::uno::Reference<css::lang::XEventListener> const& rxListener)
48
0
{
49
0
    std::unique_lock aGuard(m_aMutex);
50
0
    maEventListeners.removeInterface(aGuard, rxListener);
51
0
}
52
53
css::uno::Any SAL_CALL WeakComponentImplHelperBase2::queryInterface(css::uno::Type const& rType)
54
165
{
55
165
    css::uno::Any aReturn = ::cppu::queryInterface(rType, static_cast<css::uno::XWeak*>(this),
56
165
                                                   static_cast<css::lang::XComponent*>(this));
57
165
    if (aReturn.hasValue())
58
109
        return aReturn;
59
56
    return OWeakObject::queryInterface(rType);
60
165
}
61
62
static void checkInterface(css::uno::Type const& rType)
63
24.9k
{
64
24.9k
    if (css::uno::TypeClass_INTERFACE != rType.getTypeClass())
65
0
    {
66
0
        OUString msg("querying for interface \"" + rType.getTypeName() + "\": no interface type!");
67
0
        SAL_WARN("cppuhelper", msg);
68
0
        throw css::uno::RuntimeException(msg);
69
0
    }
70
24.9k
}
71
72
static bool isXInterface(rtl_uString* pStr)
73
24.9k
{
74
24.9k
    return OUString::unacquired(&pStr) == "com.sun.star.uno.XInterface";
75
24.9k
}
76
77
static bool td_equals(typelib_TypeDescriptionReference const* pTDR1,
78
                      typelib_TypeDescriptionReference const* pTDR2)
79
50.6k
{
80
50.6k
    return ((pTDR1 == pTDR2)
81
25.9k
            || OUString::unacquired(&pTDR1->pTypeName) == OUString::unacquired(&pTDR2->pTypeName));
82
50.6k
}
83
84
static void* makeInterface(sal_IntPtr nOffset, void* that)
85
24.7k
{
86
24.7k
    return (static_cast<char*>(that) + nOffset);
87
24.7k
}
88
89
static bool recursivelyFindType(typelib_TypeDescriptionReference const* demandedType,
90
                                typelib_InterfaceTypeDescription const* type, sal_IntPtr* offset)
91
551
{
92
    // This code assumes that the vtables of a multiple-inheritance class (the
93
    // offset amount by which to adjust the this pointer) follow one another in
94
    // the object layout, and that they contain slots for the inherited classes
95
    // in a specific order.  In theory, that need not hold for any given
96
    // platform; in practice, it seems to work well on all supported platforms:
97
793
next:
98
1.34k
    for (sal_Int32 i = 0; i < type->nBaseTypes; ++i)
99
793
    {
100
793
        if (i > 0)
101
0
        {
102
0
            *offset += sizeof(void*);
103
0
        }
104
793
        typelib_InterfaceTypeDescription const* base = type->ppBaseTypes[i];
105
        // ignore XInterface:
106
793
        if (base->nBaseTypes > 0)
107
242
        {
108
242
            if (td_equals(reinterpret_cast<typelib_TypeDescriptionReference const*>(base),
109
242
                          demandedType))
110
0
            {
111
0
                return true;
112
0
            }
113
            // Profiling showed that it is important to speed up the common case
114
            // of only one base:
115
242
            if (type->nBaseTypes == 1)
116
242
            {
117
242
                type = base;
118
242
                goto next;
119
242
            }
120
0
            if (recursivelyFindType(demandedType, base, offset))
121
0
            {
122
0
                return true;
123
0
            }
124
0
        }
125
793
    }
126
551
    return false;
127
793
}
128
129
static void* queryDeepNoXInterface(typelib_TypeDescriptionReference const* pDemandedTDR,
130
                                   cppu::class_data* cd, void* that)
131
24.8k
{
132
24.8k
    cppu::type_entry* pEntries = getTypeEntries(cd);
133
24.8k
    sal_Int32 nTypes = cd->m_nTypes;
134
24.8k
    sal_Int32 n;
135
136
    // try top interfaces without getting td
137
50.5k
    for (n = 0; n < nTypes; ++n)
138
50.4k
    {
139
50.4k
        if (td_equals(pEntries[n].m_type.typeRef, pDemandedTDR))
140
24.7k
        {
141
24.7k
            return makeInterface(pEntries[n].m_offset, that);
142
24.7k
        }
143
50.4k
    }
144
    // query deep getting td
145
666
    for (n = 0; n < nTypes; ++n)
146
551
    {
147
551
        typelib_TypeDescription* pTD = nullptr;
148
551
        TYPELIB_DANGER_GET(&pTD, pEntries[n].m_type.typeRef);
149
551
        if (pTD)
150
551
        {
151
            // exclude top (already tested) and bottom (XInterface) interface
152
551
            OSL_ENSURE(reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD)->nBaseTypes > 0,
153
551
                       "### want to implement XInterface:"
154
551
                       " template argument is XInterface?!?!?!");
155
551
            sal_IntPtr offset = pEntries[n].m_offset;
156
551
            bool found = recursivelyFindType(
157
551
                pDemandedTDR, reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD), &offset);
158
551
            TYPELIB_DANGER_RELEASE(pTD);
159
551
            if (found)
160
0
            {
161
0
                return makeInterface(offset, that);
162
0
            }
163
551
        }
164
0
        else
165
0
        {
166
0
            OUString msg("cannot get type description for type \""
167
0
                         + OUString::unacquired(&pEntries[n].m_type.typeRef->pTypeName) + "\"!");
168
0
            SAL_WARN("cppuhelper", msg);
169
0
            throw css::uno::RuntimeException(msg);
170
0
        }
171
551
    }
172
115
    return nullptr;
173
115
}
174
175
css::uno::Any WeakComponentImplHelper_query(css::uno::Type const& rType, cppu::class_data* cd,
176
                                            WeakComponentImplHelperBase2* pBase)
177
24.9k
{
178
24.9k
    checkInterface(rType);
179
24.9k
    typelib_TypeDescriptionReference* pTDR = rType.getTypeLibType();
180
181
    // shortcut XInterface to WeakComponentImplHelperBase
182
24.9k
    if (!isXInterface(pTDR->pTypeName))
183
24.8k
    {
184
24.8k
        void* p = queryDeepNoXInterface(pTDR, cd, pBase);
185
24.8k
        if (p)
186
24.7k
        {
187
24.7k
            return css::uno::Any(&p, pTDR);
188
24.7k
        }
189
24.8k
    }
190
165
    return pBase->cppuhelper::WeakComponentImplHelperBase2::queryInterface(rType);
191
24.9k
}
192
193
} // namespace cppuextra
194
195
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */