1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_bridges.hxx"
26 
27 #include "bridges/cpp_uno/shared/vtables.hxx"
28 
29 #include "osl/diagnose.h"
30 #include "sal/types.h"
31 #include "typelib/typedescription.h"
32 
33 #include <algorithm>
34 
35 namespace
36 {
37 
38 /**
39  *  Calculates the number of vtables associated with an interface type.
40  *
41  * <p>Multiple-inheritance C++ classes have more than one vtable.</p>
42  *
43  * @param type a non-null pointer to an interface type description
44  * @return the number of vtables associated with the given interface type
45  */
getVtableCount(typelib_InterfaceTypeDescription const * type)46 sal_Int32 getVtableCount(typelib_InterfaceTypeDescription const * type) {
47     sal_Int32 n = 0;
48     for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) {
49         n += getVtableCount(type->ppBaseTypes[i]);
50     }
51     return std::max< sal_Int32 >(n, 1);
52 }
53 
54 /**
55  * Maps a local member index to a local function index.
56  *
57  * <p><em>Local</em> members/functions are those not inherited from any base
58  * types.  The number of <em>functions</em> is potentially larger than the
59  * number of <em>members</em>, as each read&ndash;write attribute member counts
60  * as two functions.</p>
61  *
62  * @param type a non-null pointer to an interface type description
63  * @param localMember a local member index, relative to the given interface type
64  * @return the local function index corresponding to the given local member
65  *     index, relative to the given interface type
66  */
mapLocalMemberToLocalFunction(typelib_InterfaceTypeDescription * type,sal_Int32 localMember)67 sal_Int32 mapLocalMemberToLocalFunction(
68     typelib_InterfaceTypeDescription * type, sal_Int32 localMember)
69 {
70     typelib_typedescription_complete(
71         reinterpret_cast< typelib_TypeDescription ** >(&type));
72     sal_Int32 localMemberOffset = type->nAllMembers - type->nMembers;
73     sal_Int32 localFunctionOffset = type->nMapFunctionIndexToMemberIndex
74         - bridges::cpp_uno::shared::getLocalFunctions(type);
75     return type->pMapMemberIndexToFunctionIndex[localMemberOffset + localMember]
76         - localFunctionOffset;
77 }
78 
79 // Since on Solaris we compile with --instances=static, getVtableSlot cannot be
80 // a template function, with explicit instantiates for
81 // T = typelib_InterfaceAttributeTypeDescription and
82 // T = typelib_InterfaceMethodTypeDescription in this file; hence, there are two
83 // overloaded versions of getVtableSlot that both delegate to this template
84 // function:
doGetVtableSlot(T const * ifcMember)85 template< typename T > bridges::cpp_uno::shared::VtableSlot doGetVtableSlot(
86     T const * ifcMember)
87 {
88     bridges::cpp_uno::shared::VtableSlot slot;
89     slot.offset = 0;
90     T * member = const_cast< T * >(ifcMember);
91     while (member->pBaseRef != 0) {
92         OSL_ASSERT(member->nIndex < member->pInterface->nBaseTypes);
93         for (sal_Int32 i = 0; i < member->nIndex; ++i) {
94             slot.offset += getVtableCount(member->pInterface->ppBaseTypes[i]);
95         }
96         typelib_TypeDescription * desc = 0;
97         typelib_typedescriptionreference_getDescription(
98             &desc, member->pBaseRef);
99         OSL_ASSERT(
100             desc != 0 && desc->eTypeClass == member->aBase.aBase.eTypeClass);
101         if (member != ifcMember) {
102             typelib_typedescription_release(&member->aBase.aBase);
103         }
104         member = reinterpret_cast< T * >(desc);
105     }
106     slot.index
107         = bridges::cpp_uno::shared::getPrimaryFunctions(
108             member->pInterface->pBaseTypeDescription)
109         + mapLocalMemberToLocalFunction(member->pInterface, member->nIndex);
110     if (member != ifcMember) {
111         typelib_typedescription_release(&member->aBase.aBase);
112     }
113     return slot;
114 }
115 
116 }
117 
118 namespace bridges { namespace cpp_uno { namespace shared {
119 
getLocalFunctions(typelib_InterfaceTypeDescription const * type)120 sal_Int32 getLocalFunctions(typelib_InterfaceTypeDescription const * type) {
121     return type->nMembers == 0
122         ? 0
123         : (type->nMapFunctionIndexToMemberIndex
124            - type->pMapMemberIndexToFunctionIndex[
125                type->nAllMembers - type->nMembers]);
126 }
127 
getPrimaryFunctions(typelib_InterfaceTypeDescription * type)128 sal_Int32 getPrimaryFunctions(typelib_InterfaceTypeDescription * type) {
129     sal_Int32 n = 0;
130     for (; type != 0; type = type->pBaseTypeDescription) {
131         typelib_typedescription_complete(
132             reinterpret_cast< typelib_TypeDescription ** >(&type));
133         n += getLocalFunctions(type);
134     }
135     return n;
136 }
137 
getVtableSlot(typelib_InterfaceAttributeTypeDescription const * ifcMember)138 VtableSlot getVtableSlot(
139     typelib_InterfaceAttributeTypeDescription const * ifcMember)
140 {
141     return doGetVtableSlot(ifcMember);
142 }
143 
getVtableSlot(typelib_InterfaceMethodTypeDescription const * ifcMember)144 VtableSlot getVtableSlot(
145     typelib_InterfaceMethodTypeDescription const * ifcMember)
146 {
147     return doGetVtableSlot(ifcMember);
148 }
149 
150 } } }
151