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 #ifndef INCLUDED_COM_SUN_STAR_UNO_REFERENCE_HXX
20 #define INCLUDED_COM_SUN_STAR_UNO_REFERENCE_HXX
21 
22 #include "sal/config.h"
23 
24 #include <cstddef>
25 #include <ostream>
26 
27 #include "com/sun/star/uno/Reference.h"
28 #include "com/sun/star/uno/RuntimeException.hpp"
29 #include "com/sun/star/uno/XInterface.hpp"
30 #include "com/sun/star/uno/Any.hxx"
31 #include "cppu/cppudllapi.h"
32 
33 extern "C" CPPU_DLLPUBLIC rtl_uString * SAL_CALL cppu_unsatisfied_iquery_msg(
34     typelib_TypeDescriptionReference * pType )
35     SAL_THROW_EXTERN_C();
36 extern "C" CPPU_DLLPUBLIC rtl_uString * SAL_CALL cppu_unsatisfied_iset_msg(
37     typelib_TypeDescriptionReference * pType )
38     SAL_THROW_EXTERN_C();
39 
40 namespace com
41 {
42 namespace sun
43 {
44 namespace star
45 {
46 namespace uno
47 {
48 
49 
iquery(XInterface * pInterface,const Type & rType)50 inline XInterface * BaseReference::iquery(
51     XInterface * pInterface, const Type & rType )
52 {
53     if (pInterface)
54     {
55         Any aRet( pInterface->queryInterface( rType ) );
56         if (typelib_TypeClass_INTERFACE == aRet.pType->eTypeClass)
57         {
58             XInterface * pRet = static_cast< XInterface * >( aRet.pReserved );
59             aRet.pReserved = NULL;
60             return pRet;
61         }
62     }
63     return NULL;
64 }
65 
66 template< class interface_type >
iquery(XInterface * pInterface)67 inline XInterface * Reference< interface_type >::iquery(
68     XInterface * pInterface )
69 {
70     return BaseReference::iquery(pInterface, interface_type::static_type());
71 }
72 
iquery_throw(XInterface * pInterface,const Type & rType)73 inline XInterface * BaseReference::iquery_throw(
74     XInterface * pInterface, const Type & rType )
75 {
76     XInterface * pQueried = iquery( pInterface, rType );
77     if (pQueried)
78         return pQueried;
79     throw RuntimeException(
80         ::rtl::OUString( cppu_unsatisfied_iquery_msg( rType.getTypeLibType() ), SAL_NO_ACQUIRE ),
81         Reference< XInterface >( pInterface ) );
82 }
83 
84 template< class interface_type >
iquery_throw(XInterface * pInterface)85 inline XInterface * Reference< interface_type >::iquery_throw(
86     XInterface * pInterface )
87 {
88     return BaseReference::iquery_throw(
89         pInterface, interface_type::static_type());
90 }
91 
92 template< class interface_type >
iset_throw(interface_type * pInterface)93 inline interface_type * Reference< interface_type >::iset_throw(
94     interface_type * pInterface )
95 {
96     if (pInterface)
97     {
98         castToXInterface(pInterface)->acquire();
99         return pInterface;
100     }
101     throw RuntimeException(
102         ::rtl::OUString( cppu_unsatisfied_iset_msg( interface_type::static_type().getTypeLibType() ), SAL_NO_ACQUIRE ),
103         NULL );
104 }
105 
106 template< class interface_type >
~Reference()107 inline Reference< interface_type >::~Reference() COVERITY_NOEXCEPT_FALSE
108 {
109     if (_pInterface)
110         _pInterface->release();
111 }
112 
113 template< class interface_type >
Reference()114 inline Reference< interface_type >::Reference()
115 {
116     _pInterface = NULL;
117 }
118 
119 template< class interface_type >
Reference(const Reference<interface_type> & rRef)120 inline Reference< interface_type >::Reference( const Reference< interface_type > & rRef )
121 {
122     _pInterface = rRef._pInterface;
123     if (_pInterface)
124         _pInterface->acquire();
125 }
126 
127 #if defined LIBO_INTERNAL_ONLY
128 template< class interface_type >
Reference(Reference<interface_type> && rRef)129 inline Reference< interface_type >::Reference( Reference< interface_type > && rRef ) noexcept
130 {
131     _pInterface = rRef._pInterface;
132     rRef._pInterface = nullptr;
133 }
134 #endif
135 
136 template< class interface_type > template< class derived_type >
Reference(const Reference<derived_type> & rRef,typename detail::UpCast<interface_type,derived_type>::t)137 inline Reference< interface_type >::Reference(
138     const Reference< derived_type > & rRef,
139     typename detail::UpCast< interface_type, derived_type >::t )
140 {
141     interface_type * p = rRef.get();
142     _pInterface = p;
143     if (_pInterface)
144         _pInterface->acquire();
145 }
146 
147 template< class interface_type >
Reference(interface_type * pInterface)148 inline Reference< interface_type >::Reference( interface_type * pInterface )
149 {
150     _pInterface = castToXInterface(pInterface);
151     if (_pInterface)
152         _pInterface->acquire();
153 }
154 
155 template< class interface_type >
Reference(interface_type * pInterface,__sal_NoAcquire)156 inline Reference< interface_type >::Reference( interface_type * pInterface, __sal_NoAcquire )
157 {
158     _pInterface = castToXInterface(pInterface);
159 }
160 
161 template< class interface_type >
Reference(interface_type * pInterface,UnoReference_NoAcquire)162 inline Reference< interface_type >::Reference( interface_type * pInterface, UnoReference_NoAcquire )
163 {
164     _pInterface = castToXInterface(pInterface);
165 }
166 
167 template< class interface_type >
Reference(const BaseReference & rRef,UnoReference_Query)168 inline Reference< interface_type >::Reference( const BaseReference & rRef, UnoReference_Query )
169 {
170     _pInterface = iquery( rRef.get() );
171 }
172 
173 template< class interface_type >
Reference(XInterface * pInterface,UnoReference_Query)174 inline Reference< interface_type >::Reference( XInterface * pInterface, UnoReference_Query )
175 {
176     _pInterface = iquery( pInterface );
177 }
178 
179 template< class interface_type >
Reference(const Any & rAny,UnoReference_Query)180 inline Reference< interface_type >::Reference( const Any & rAny, UnoReference_Query )
181 {
182     _pInterface = (typelib_TypeClass_INTERFACE == rAny.pType->eTypeClass
183                    ? iquery( static_cast< XInterface * >( rAny.pReserved ) ) : NULL);
184 }
185 
186 template< class interface_type >
Reference(const BaseReference & rRef,UnoReference_QueryThrow)187 inline Reference< interface_type >::Reference( const BaseReference & rRef, UnoReference_QueryThrow )
188 {
189     _pInterface = iquery_throw( rRef.get() );
190 }
191 
192 template< class interface_type >
Reference(XInterface * pInterface,UnoReference_QueryThrow)193 inline Reference< interface_type >::Reference( XInterface * pInterface, UnoReference_QueryThrow )
194 {
195     _pInterface = iquery_throw( pInterface );
196 }
197 
198 template< class interface_type >
Reference(const Any & rAny,UnoReference_QueryThrow)199 inline Reference< interface_type >::Reference( const Any & rAny, UnoReference_QueryThrow )
200 {
201     _pInterface = iquery_throw( typelib_TypeClass_INTERFACE == rAny.pType->eTypeClass
202                                 ? static_cast< XInterface * >( rAny.pReserved ) : NULL );
203 }
204 
205 template< class interface_type >
Reference(const Reference<interface_type> & rRef,UnoReference_SetThrow)206 inline Reference< interface_type >::Reference( const Reference< interface_type > & rRef, UnoReference_SetThrow )
207 {
208     _pInterface = castToXInterface( iset_throw( rRef.get() ) );
209 }
210 
211 template< class interface_type >
Reference(interface_type * pInterface,UnoReference_SetThrow)212 inline Reference< interface_type >::Reference( interface_type * pInterface, UnoReference_SetThrow )
213 {
214     _pInterface = castToXInterface( iset_throw( pInterface ) );
215 }
216 
217 
218 template< class interface_type >
clear()219 inline void Reference< interface_type >::clear()
220 {
221     if (_pInterface)
222     {
223         XInterface * const pOld = _pInterface;
224         _pInterface = NULL;
225         pOld->release();
226     }
227 }
228 
229 template< class interface_type >
set(interface_type * pInterface)230 inline bool Reference< interface_type >::set(
231     interface_type * pInterface )
232 {
233     if (pInterface)
234         castToXInterface(pInterface)->acquire();
235     XInterface * const pOld = _pInterface;
236     _pInterface = castToXInterface(pInterface);
237     if (pOld)
238         pOld->release();
239     return (NULL != pInterface);
240 }
241 
242 template< class interface_type >
set(interface_type * pInterface,__sal_NoAcquire)243 inline bool Reference< interface_type >::set(
244     interface_type * pInterface, __sal_NoAcquire )
245 {
246     XInterface * const pOld = _pInterface;
247     _pInterface = castToXInterface(pInterface);
248     if (pOld)
249         pOld->release();
250     return (NULL != pInterface);
251 }
252 
253 template< class interface_type >
set(interface_type * pInterface,UnoReference_NoAcquire)254 inline bool Reference< interface_type >::set(
255     interface_type * pInterface, UnoReference_NoAcquire )
256 {
257     return set( pInterface, SAL_NO_ACQUIRE );
258 }
259 
260 
261 template< class interface_type >
set(const Reference<interface_type> & rRef)262 inline bool Reference< interface_type >::set(
263     const Reference< interface_type > & rRef )
264 {
265     return set( castFromXInterface( rRef._pInterface ) );
266 }
267 
268 template< class interface_type >
set(XInterface * pInterface,UnoReference_Query)269 inline bool Reference< interface_type >::set(
270     XInterface * pInterface, UnoReference_Query )
271 {
272     return set( castFromXInterface(iquery( pInterface )), SAL_NO_ACQUIRE );
273 }
274 
275 template< class interface_type >
set(const BaseReference & rRef,UnoReference_Query)276 inline bool Reference< interface_type >::set(
277     const BaseReference & rRef, UnoReference_Query )
278 {
279     return set( castFromXInterface(iquery( rRef.get() )), SAL_NO_ACQUIRE );
280 }
281 
282 
283 template< class interface_type >
set(Any const & rAny,UnoReference_Query)284 inline bool Reference< interface_type >::set(
285     Any const & rAny, UnoReference_Query )
286 {
287     return set(
288         castFromXInterface(
289             iquery(
290                 rAny.pType->eTypeClass == typelib_TypeClass_INTERFACE
291                 ? static_cast< XInterface * >( rAny.pReserved ) : NULL )),
292         SAL_NO_ACQUIRE );
293 }
294 
295 
296 template< class interface_type >
set(XInterface * pInterface,UnoReference_QueryThrow)297 inline void Reference< interface_type >::set(
298     XInterface * pInterface, UnoReference_QueryThrow )
299 {
300     set( castFromXInterface(iquery_throw( pInterface )), SAL_NO_ACQUIRE );
301 }
302 
303 template< class interface_type >
set(const BaseReference & rRef,UnoReference_QueryThrow)304 inline void Reference< interface_type >::set(
305     const BaseReference & rRef, UnoReference_QueryThrow )
306 {
307     set( castFromXInterface(iquery_throw( rRef.get() )), SAL_NO_ACQUIRE );
308 }
309 
310 
311 template< class interface_type >
set(Any const & rAny,UnoReference_QueryThrow)312 inline void Reference< interface_type >::set(
313     Any const & rAny, UnoReference_QueryThrow )
314 {
315     set( castFromXInterface(
316              iquery_throw(
317                  rAny.pType->eTypeClass == typelib_TypeClass_INTERFACE
318                  ? static_cast< XInterface * >( rAny.pReserved ) : NULL )),
319          SAL_NO_ACQUIRE );
320 }
321 
322 template< class interface_type >
set(interface_type * pInterface,UnoReference_SetThrow)323 inline void Reference< interface_type >::set(
324     interface_type * pInterface, UnoReference_SetThrow )
325 {
326     set( iset_throw( pInterface ), SAL_NO_ACQUIRE );
327 }
328 
329 template< class interface_type >
set(const Reference<interface_type> & rRef,UnoReference_SetThrow)330 inline void Reference< interface_type >::set(
331     const Reference< interface_type > & rRef, UnoReference_SetThrow )
332 {
333     set( rRef.get(), UNO_SET_THROW );
334 }
335 
336 
337 template< class interface_type >
operator =(interface_type * pInterface)338 inline Reference< interface_type > & Reference< interface_type >::operator = (
339     interface_type * pInterface )
340 {
341     set( pInterface );
342     return *this;
343 }
344 
345 template< class interface_type >
operator =(const Reference<interface_type> & rRef)346 inline Reference< interface_type > & Reference< interface_type >::operator = (
347     const Reference< interface_type > & rRef )
348 {
349     set( castFromXInterface( rRef._pInterface ) );
350     return *this;
351 }
352 
353 #if defined LIBO_INTERNAL_ONLY
354 template< class interface_type >
operator =(Reference<interface_type> && rRef)355 inline Reference< interface_type > & Reference< interface_type >::operator = (
356      Reference< interface_type > && rRef ) noexcept
357 {
358     if (_pInterface)
359         _pInterface->release();
360     _pInterface = rRef._pInterface;
361     rRef._pInterface = nullptr;
362     return *this;
363 }
364 #endif
365 
366 template< class interface_type >
query(const BaseReference & rRef)367 inline Reference< interface_type > Reference< interface_type >::query(
368     const BaseReference & rRef )
369 {
370     return Reference< interface_type >(
371         castFromXInterface(iquery( rRef.get() )), SAL_NO_ACQUIRE );
372 }
373 
374 template< class interface_type >
query(XInterface * pInterface)375 inline Reference< interface_type > Reference< interface_type >::query(
376     XInterface * pInterface )
377 {
378     return Reference< interface_type >(
379         castFromXInterface(iquery( pInterface )), SAL_NO_ACQUIRE );
380 }
381 
382 
operator ==(XInterface * pInterface) const383 inline bool BaseReference::operator == ( XInterface * pInterface ) const
384 {
385     if (_pInterface == pInterface)
386         return true;
387     try
388     {
389         // only the query to XInterface must return the same pointer if they belong to same objects
390         Reference< XInterface > x1( _pInterface, UNO_QUERY );
391         Reference< XInterface > x2( pInterface, UNO_QUERY );
392         return (x1._pInterface == x2._pInterface);
393     }
394     catch (RuntimeException &)
395     {
396         return false;
397     }
398 }
399 
400 
operator <(const BaseReference & rRef) const401 inline bool BaseReference::operator < (
402     const BaseReference & rRef ) const
403 {
404     if (_pInterface == rRef._pInterface)
405         return false;
406     try
407     {
408         // only the query to XInterface must return the same pointer:
409         Reference< XInterface > x1( _pInterface, UNO_QUERY );
410         Reference< XInterface > x2( rRef, UNO_QUERY );
411         return (x1._pInterface < x2._pInterface);
412     }
413     catch (RuntimeException &)
414     {
415         return false;
416     }
417 }
418 
419 
operator !=(XInterface * pInterface) const420 inline bool BaseReference::operator != ( XInterface * pInterface ) const
421 {
422     return (! operator == ( pInterface ));
423 }
424 
operator ==(const BaseReference & rRef) const425 inline bool BaseReference::operator == ( const BaseReference & rRef ) const
426 {
427     return operator == ( rRef._pInterface );
428 }
429 
operator !=(const BaseReference & rRef) const430 inline bool BaseReference::operator != ( const BaseReference & rRef ) const
431 {
432     return (! operator == ( rRef._pInterface ));
433 }
434 
435 #if defined LIBO_INTERNAL_ONLY
436 /**
437    Support for BaseReference in std::ostream (and thus in CPPUNIT_ASSERT or
438    SAL_INFO macros, for example).
439 
440    @since LibreOffice 5.4
441 */
442 template<typename charT, typename traits> std::basic_ostream<charT, traits> &
operator <<(std::basic_ostream<charT,traits> & stream,BaseReference const & ref)443 operator <<(
444     std::basic_ostream<charT, traits> & stream, BaseReference const & ref)
445 { return stream << ref.get(); }
446 #endif
447 
448 }
449 }
450 }
451 }
452 
453 #if defined LIBO_INTERNAL_ONLY
454 namespace std
455 {
456 
457 /**
458   Make css::uno::Reference hashable by default for use in STL containers.
459 
460   @since LibreOffice 6.3
461 */
462 template<typename T>
463 struct hash<::css::uno::Reference<T>>
464 {
operator ()std::hash465     std::size_t operator()(::css::uno::Reference<T> const & s) const
466     { return size_t(s.get()); }
467 };
468 
469 }
470 
471 #endif
472 
473 #endif
474 
475 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
476