Line data Source code
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 :
21 : #include "bridges/cpp_uno/shared/vtables.hxx"
22 :
23 : #include "osl/diagnose.h"
24 : #include "sal/types.h"
25 : #include "typelib/typedescription.h"
26 :
27 : #include <algorithm>
28 :
29 : namespace
30 : {
31 :
32 : /**
33 : * Calculates the number of vtables associated with an interface type.
34 : *
35 : * <p>Multiple-inheritance C++ classes have more than one vtable.</p>
36 : *
37 : * @param type a non-null pointer to an interface type description
38 : * @return the number of vtables associated with the given interface type
39 : */
40 170 : sal_Int32 getVtableCount(typelib_InterfaceTypeDescription const * type) {
41 170 : sal_Int32 n = 0;
42 298 : for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) {
43 128 : n += getVtableCount(type->ppBaseTypes[i]);
44 : }
45 170 : return std::max< sal_Int32 >(n, 1);
46 : }
47 :
48 : /**
49 : * Maps a local member index to a local function index.
50 : *
51 : * <p><em>Local</em> members/functions are those not inherited from any base
52 : * types. The number of <em>functions</em> is potentially larger than the
53 : * number of <em>members</em>, as each read–write attribute member counts
54 : * as two functions.</p>
55 : *
56 : * @param type a non-null pointer to an interface type description
57 : * @param localMember a local member index, relative to the given interface type
58 : * @return the local function index corresponding to the given local member
59 : * index, relative to the given interface type
60 : */
61 436 : sal_Int32 mapLocalMemberToLocalFunction(
62 : typelib_InterfaceTypeDescription * type, sal_Int32 localMember)
63 : {
64 : typelib_typedescription_complete(
65 436 : reinterpret_cast< typelib_TypeDescription ** >(&type));
66 436 : sal_Int32 localMemberOffset = type->nAllMembers - type->nMembers;
67 : sal_Int32 localFunctionOffset = type->nMapFunctionIndexToMemberIndex
68 436 : - bridges::cpp_uno::shared::getLocalFunctions(type);
69 436 : return type->pMapMemberIndexToFunctionIndex[localMemberOffset + localMember]
70 436 : - localFunctionOffset;
71 : }
72 :
73 : // Since on Solaris we compile with --instances=static, getVtableSlot cannot be
74 : // a template function, with explicit instantiates for
75 : // T = typelib_InterfaceAttributeTypeDescription and
76 : // T = typelib_InterfaceMethodTypeDescription in this file; hence, there are two
77 : // overloaded versions of getVtableSlot that both delegate to this template
78 : // function:
79 436 : template< typename T > bridges::cpp_uno::shared::VtableSlot doGetVtableSlot(
80 : T const * ifcMember)
81 : {
82 : bridges::cpp_uno::shared::VtableSlot slot;
83 436 : slot.offset = 0;
84 436 : T * member = const_cast< T * >(ifcMember);
85 1207 : while (member->pBaseRef != 0) {
86 : OSL_ASSERT(member->nIndex < member->pInterface->nBaseTypes);
87 377 : for (sal_Int32 i = 0; i < member->nIndex; ++i) {
88 42 : slot.offset += getVtableCount(member->pInterface->ppBaseTypes[i]);
89 : }
90 335 : typelib_TypeDescription * desc = 0;
91 335 : typelib_typedescriptionreference_getDescription(
92 : &desc, member->pBaseRef);
93 : OSL_ASSERT(
94 : desc != 0 && desc->eTypeClass == member->aBase.aBase.eTypeClass);
95 335 : if (member != ifcMember) {
96 99 : typelib_typedescription_release(&member->aBase.aBase);
97 : }
98 335 : member = reinterpret_cast< T * >(desc);
99 : }
100 436 : slot.index
101 : = bridges::cpp_uno::shared::getPrimaryFunctions(
102 : member->pInterface->pBaseTypeDescription)
103 : + mapLocalMemberToLocalFunction(member->pInterface, member->nIndex);
104 436 : if (member != ifcMember) {
105 236 : typelib_typedescription_release(&member->aBase.aBase);
106 : }
107 436 : return slot;
108 : }
109 :
110 : }
111 :
112 : namespace bridges { namespace cpp_uno { namespace shared {
113 :
114 1213 : sal_Int32 getLocalFunctions(typelib_InterfaceTypeDescription const * type) {
115 : return type->nMembers == 0
116 : ? 0
117 : : (type->nMapFunctionIndexToMemberIndex
118 : - type->pMapMemberIndexToFunctionIndex[
119 1213 : type->nAllMembers - type->nMembers]);
120 : }
121 :
122 472 : sal_Int32 getPrimaryFunctions(typelib_InterfaceTypeDescription * type) {
123 472 : sal_Int32 n = 0;
124 1098 : for (; type != 0; type = type->pBaseTypeDescription) {
125 : typelib_typedescription_complete(
126 626 : reinterpret_cast< typelib_TypeDescription ** >(&type));
127 626 : n += getLocalFunctions(type);
128 : }
129 472 : return n;
130 : }
131 :
132 93 : VtableSlot getVtableSlot(
133 : typelib_InterfaceAttributeTypeDescription const * ifcMember)
134 : {
135 93 : return doGetVtableSlot(ifcMember);
136 : }
137 :
138 343 : VtableSlot getVtableSlot(
139 : typelib_InterfaceMethodTypeDescription const * ifcMember)
140 : {
141 343 : return doGetVtableSlot(ifcMember);
142 : }
143 :
144 : } } }
145 :
146 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|