1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
25 #include <rtl/strbuf.hxx>
26 #include <rtl/ustrbuf.hxx>
27 #include <osl/mutex.hxx>
29 #include <com/sun/star/uno/genfunc.hxx>
30 #include <typelib/typedescription.hxx>
32 #include <unordered_map>
36 using namespace ::std
;
37 using namespace ::osl
;
38 using namespace ::com::sun::star::uno
;
39 using namespace ::__cxxabiv1
;
42 namespace CPPU_CURRENT_NAMESPACE
45 void dummy_can_throw_anything( char const * )
49 static OUString
toUNOname( char const * p
)
51 #if OSL_DEBUG_LEVEL > 1
52 char const * start
= p
;
55 // example: N3com3sun4star4lang24IllegalArgumentExceptionE
57 OUStringBuffer
buf( 64 );
64 long n
= (*p
++ - '0');
65 while ('0' <= *p
&& '9' >= *p
)
70 buf
.appendAscii( p
, n
);
76 #if OSL_DEBUG_LEVEL > 1
77 OUString
ret( buf
.makeStringAndClear() );
78 OString
c_ret( OUStringToOString( ret
, RTL_TEXTENCODING_ASCII_US
) );
79 fprintf( stderr
, "> toUNOname(): %s => %s\n", start
, c_ret
.getStr() );
82 return buf
.makeStringAndClear();
88 typedef std::unordered_map
< OUString
, type_info
* > t_rtti_map
;
92 t_rtti_map m_generatedRttis
;
100 type_info
* getRTTI( typelib_CompoundTypeDescription
* );
104 : m_hApp( dlopen( 0, RTLD_LAZY
) )
114 type_info
* RTTI::getRTTI( typelib_CompoundTypeDescription
*pTypeDescr
)
118 OUString
const & unoName
= *(OUString
const *)&pTypeDescr
->aBase
.pTypeName
;
120 MutexGuard
guard( m_mutex
);
121 t_rtti_map::const_iterator
iRttiFind( m_rttis
.find( unoName
) );
122 if (iRttiFind
== m_rttis
.end())
125 OStringBuffer
buf( 64 );
126 buf
.append( "_ZTIN" );
130 OUString
token( unoName
.getToken( 0, '.', index
) );
131 buf
.append( token
.getLength() );
132 OString
c_token( OUStringToOString( token
, RTL_TEXTENCODING_ASCII_US
) );
133 buf
.append( c_token
);
138 OString
symName( buf
.makeStringAndClear() );
139 rtti
= (type_info
*)dlsym( m_hApp
, symName
.getStr() );
143 pair
< t_rtti_map::iterator
, bool > insertion(
144 m_rttis
.insert( t_rtti_map::value_type( unoName
, rtti
) ) );
145 assert(insertion
.second
&& "### inserting new rtti failed?!");
149 // try to lookup the symbol in the generated rtti map
150 t_rtti_map::const_iterator
iFind( m_generatedRttis
.find( unoName
) );
151 if (iFind
== m_generatedRttis
.end())
153 // we must generate it !
154 // symbol and rtti-name is nearly identical,
155 // the symbol is prefixed with _ZTI
156 char const * rttiName
= symName
.getStr() +4;
157 #if OSL_DEBUG_LEVEL > 1
158 fprintf( stderr
,"generated rtti for %s\n", rttiName
);
160 if (pTypeDescr
->pBaseTypeDescription
)
162 // ensure availability of base
163 type_info
* base_rtti
= getRTTI(
164 (typelib_CompoundTypeDescription
*)pTypeDescr
->pBaseTypeDescription
);
165 rtti
= new __si_class_type_info(
166 strdup( rttiName
), (__class_type_info
*)base_rtti
);
170 // this class has no base class
171 rtti
= new __class_type_info( strdup( rttiName
) );
174 pair
< t_rtti_map::iterator
, bool > insertion(
175 m_generatedRttis
.insert( t_rtti_map::value_type( unoName
, rtti
) ) );
176 assert(insertion
.second
&& "### inserting new generated rtti failed?!");
178 else // taking already generated rtti
180 rtti
= iFind
->second
;
186 rtti
= iRttiFind
->second
;
193 static void deleteException( void * pExc
)
195 __cxa_exception
const * header
= ((__cxa_exception
const *)pExc
- 1);
196 typelib_TypeDescription
* pTD
= 0;
197 OUString
unoName( toUNOname( header
->exceptionType
->name() ) );
198 ::typelib_typedescription_getByName( &pTD
, unoName
.pData
);
199 assert(pTD
&& "### unknown exception type! leaving out destruction => leaking!!!");
202 ::uno_destructData( pExc
, pTD
, cpp_release
);
203 ::typelib_typedescription_release( pTD
);
207 void raiseException( uno_Any
* pUnoExc
, uno_Mapping
* pUno2Cpp
)
213 // construct cpp exception object
214 typelib_TypeDescription
* pTypeDescr
= 0;
215 TYPELIB_DANGER_GET( &pTypeDescr
, pUnoExc
->pType
);
219 pCppExc
= __cxa_allocate_exception( pTypeDescr
->nSize
);
220 ::uno_copyAndConvertData( pCppExc
, pUnoExc
->pData
, pTypeDescr
, pUno2Cpp
);
222 // destruct uno exception
223 ::uno_any_destruct( pUnoExc
, 0 );
224 // avoiding locked counts
225 static RTTI rtti_data
;
226 rtti
= (type_info
*)rtti_data
.getRTTI((typelib_CompoundTypeDescription
*)pTypeDescr
);
227 TYPELIB_DANGER_RELEASE( pTypeDescr
);
232 __cxa_throw( pCppExc
, rtti
, deleteException
);
235 void fillUnoException(uno_Any
* pExc
, uno_Mapping
* pCpp2Uno
)
237 __cxa_exception
* header
= __cxa_get_globals()->caughtExceptions
;
241 std::type_info
*exceptionType
= __cxa_current_exception_type();
243 typelib_TypeDescription
* pExcTypeDescr
= 0;
244 OUString
unoName( toUNOname( exceptionType
->name() ) );
245 ::typelib_typedescription_getByName( &pExcTypeDescr
, unoName
.pData
);
249 // construct uno exception any
250 ::uno_any_constructAndConvert( pExc
, header
->adjustedPtr
, pExcTypeDescr
, pCpp2Uno
);
251 ::typelib_typedescription_release( pExcTypeDescr
);
256 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */