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/.
10 #ifndef INCLUDED_O3TL_ANY_HXX
11 #define INCLUDED_O3TL_ANY_HXX
13 #include <sal/config.h>
16 #include <type_traits>
19 #include <boost/optional.hpp>
21 #include <com/sun/star/uno/Any.hxx>
22 #include <com/sun/star/uno/RuntimeException.hpp>
23 #include <com/sun/star/uno/Reference.hxx>
24 #include <com/sun/star/uno/XInterface.hpp>
25 #include <cppu/unotype.hxx>
26 #include <rtl/ustring.hxx>
27 #include <sal/types.h>
29 // Some functionality related to css::uno::Any that would ideally be part of
30 // <com/sun/star/uno/Any.hxx>, but (for now) cannot be for some reason.
38 template<typename T
> struct Optional
{ using type
= T
const *; };
39 template<> struct Optional
<void> { using type
= boost::optional
<Void
const>; };
40 template<> struct Optional
<bool> { using type
= boost::optional
<bool const>; };
41 template<> struct Optional
<sal_Int8
> {
42 using type
= boost::optional
<sal_Int8
const>;
44 template<> struct Optional
<sal_Int16
> {
45 using type
= boost::optional
<sal_Int16
const>;
47 template<> struct Optional
<sal_uInt16
> {
48 using type
= boost::optional
<sal_uInt16
const>;
50 template<> struct Optional
<sal_Int32
> {
51 using type
= boost::optional
<sal_Int32
const>;
53 template<> struct Optional
<sal_uInt32
> {
54 using type
= boost::optional
<sal_uInt32
const>;
56 template<> struct Optional
<sal_Int64
> {
57 using type
= boost::optional
<sal_Int64
const>;
59 template<> struct Optional
<sal_uInt64
> {
60 using type
= boost::optional
<sal_uInt64
const>;
62 template<> struct Optional
<float> {
63 using type
= boost::optional
<float const>;
65 template<> struct Optional
<double> {
66 using type
= boost::optional
<double const>;
68 template<typename T
> struct Optional
<css::uno::Reference
<T
>> {
69 using type
= boost::optional
<css::uno::Reference
<T
> const>;
71 template<> struct Optional
<css::uno::Reference
<css::uno::XInterface
>> {
72 using type
= css::uno::Reference
<css::uno::XInterface
> const *;
75 template<typename
> struct IsDerivedReference
: std::false_type
{};
76 template<typename T
> struct IsDerivedReference
<css::uno::Reference
<T
>>:
79 template<> struct IsDerivedReference
<css::uno::Reference
<css::uno::XInterface
>>:
83 template<typename
> struct IsUnoSequenceType
: std::false_type
{};
84 template<typename T
> struct IsUnoSequenceType
<cppu::UnoSequenceType
<T
>>:
88 template<typename T
> inline boost::optional
<T
const> tryGetConverted(
89 css::uno::Any
const & any
)
93 ? boost::optional
<T
const>(std::move(v
)) : boost::optional
<T
const>();
98 /** Try to access the value of a specific type stored in an Any.
100 In trying to obtain a value, the same set of conversions as supported by
101 ">>=" are considered.
103 The returned object is a proxy. Proxies can be either positive or negative.
104 Each proxy can be contextually converted to bool, yielding true iff the
105 proxy is positive. For a positive proxy P representing a value of requested
106 type T, for any T other than void, the expression *P yields that value of
107 type T. (Technically, the proxy is either a plain pointer or a
108 boost::optional, depending on whether a plain pointer into the given Any can
109 be returned for the specified type.)
111 @attention A proxy returned from this function must not outlive the
112 corresponding Any passed into this function (as it may constitute a pointer
113 into the Any's internals). That is the reason why this function is
114 restricted to lvalue arguments (i.e., to non-temporary Any objects), to
119 if (auto p = o3tl::tryAccess<css::beans::NamedValue>(f())) {
124 @note Ideally this would be a public member function of css::uno::Any (at
125 least conditional on LIBO_INTERNAL_ONLY, as it requires C++11). However, as
126 std::optional (which would be needed to implement the proxies) is only
127 available since C++14, we need to use boost::optional for now. But To not
128 make every entity that includes <com/sun/star/uno/Any.hxx> depend on
129 boost_headers, keep this here for now.
131 @tparam T the C++ representation of a UNO type that can be contained in a
132 UNO ANY (i.e., any UNO type other than ANY itself). The legacy C++
133 representations sal_Bool, cppu::UnoVoidType, cppu::UnoUnsignedShortType,
134 cppu::UnoCharType, and cppu::UnoSequenceType are not supported. Must be a
135 complete type or void.
137 @param any an Any value.
139 @return a positive proxy for the value of the specfied type obtained from
140 the given Any, or a negative proxy if no such value can be obtained.
142 template<typename T
> inline
143 typename
std::enable_if
<
144 !(detail::IsDerivedReference
<T
>::value
145 || detail::IsUnoSequenceType
<T
>::value
146 || std::is_base_of
<css::uno::XInterface
, T
>::value
),
147 typename
detail::Optional
<T
>::type
>::type
148 tryAccess(css::uno::Any
const & any
) {
149 // CHAR, STRING, TYPE, sequence types, enum types, struct types, exception
150 // types, and com.sun.star.uno.XInterface interface type:
151 return cppu::UnoType
<T
>::get().isAssignableFrom(any
.getValueType())
152 ? static_cast<T
const *>(any
.getValue()) : nullptr;
155 template<> inline detail::Optional
<void>::type tryAccess
<void>(
156 css::uno::Any
const & any
)
158 return any
.hasValue()
159 ? boost::optional
<detail::Void
const>()
160 : boost::optional
<detail::Void
const>(detail::Void());
163 template<> inline detail::Optional
<bool>::type tryAccess
<bool>(
164 css::uno::Any
const & any
)
166 return detail::tryGetConverted
<bool>(any
);
169 template<> inline detail::Optional
<sal_Int8
>::type tryAccess
<sal_Int8
>(
170 css::uno::Any
const & any
)
172 return detail::tryGetConverted
<sal_Int8
>(any
);
175 template<> inline detail::Optional
<sal_Int16
>::type tryAccess
<sal_Int16
>(
176 css::uno::Any
const & any
)
178 return detail::tryGetConverted
<sal_Int16
>(any
);
181 template<> inline detail::Optional
<sal_uInt16
>::type tryAccess
<sal_uInt16
>(
182 css::uno::Any
const & any
)
184 return detail::tryGetConverted
<sal_uInt16
>(any
);
187 template<> inline detail::Optional
<sal_Int32
>::type tryAccess
<sal_Int32
>(
188 css::uno::Any
const & any
)
190 return detail::tryGetConverted
<sal_Int32
>(any
);
193 template<> inline detail::Optional
<sal_uInt32
>::type tryAccess
<sal_uInt32
>(
194 css::uno::Any
const & any
)
196 return detail::tryGetConverted
<sal_uInt32
>(any
);
199 template<> inline detail::Optional
<sal_Int64
>::type tryAccess
<sal_Int64
>(
200 css::uno::Any
const & any
)
202 return detail::tryGetConverted
<sal_Int64
>(any
);
205 template<> inline detail::Optional
<sal_uInt64
>::type tryAccess
<sal_uInt64
>(
206 css::uno::Any
const & any
)
208 return detail::tryGetConverted
<sal_uInt64
>(any
);
211 template<> inline detail::Optional
<float>::type tryAccess
<float>(
212 css::uno::Any
const & any
)
214 return detail::tryGetConverted
<float>(any
);
217 template<> inline detail::Optional
<double>::type tryAccess
<double>(
218 css::uno::Any
const & any
)
220 return detail::tryGetConverted
<double>(any
);
223 template<> detail::Optional
<css::uno::Any
>::type tryAccess
<css::uno::Any
>(
224 css::uno::Any
const &) = delete;
226 template<> detail::Optional
<sal_Bool
>::type tryAccess
<sal_Bool
>(
227 css::uno::Any
const &) = delete;
231 // Already prevented by std::is_base_of<css::uno::XInterface, T> requiring T to
234 template<> detail::Optional<cppu::UnoVoidType>::type
235 tryAccess<cppu::UnoVoidType>(css::uno::Any const &) = delete;
237 template<> detail::Optional<cppu::UnoUnsignedShortType>::type
238 tryAccess<cppu::UnoUnsignedShortType>(css::uno::Any const &) = delete;
240 template<> detail::Optional<cppu::UnoCharType>::type
241 tryAccess<cppu::UnoCharType>(css::uno::Any const &) = delete;
245 template<typename T
> inline
246 typename
std::enable_if
<
247 detail::IsDerivedReference
<T
>::value
,
248 typename
detail::Optional
<T
>::type
>::type
249 tryAccess(css::uno::Any
const & any
) {
250 return detail::tryGetConverted
<T
>(any
);
253 template<typename T
> typename
detail::Optional
<T
>::type
tryAccess(
254 css::uno::Any
const volatile &&) = delete;
256 /** Access the value of a specific type stored in an Any, throwing an exception
259 @attention A proxy returned from this function must not outlive the
260 corresponding Any passed into this function (as it may constitute a pointer
261 into the Any's internals). However, unlike with tryAccess, the benefit of
262 allowing this function to operate on temporaries appears to outweigh its
265 @note Ideally this would be a public member function of css::uno::Any. See
266 tryAccess for details.
268 @tparam T the C++ representation of a UNO type that can be contained in a
269 UNO ANY. See tryAccess for details.
271 @param any an Any value.
273 @return a positive proxy for the value of the specfied type obtained from
274 the given Any. See tryAccess for details.
276 @throws css::uno::RuntimeException when a value of the requested type
279 template<typename T
> inline typename
detail::Optional
<T
>::type
doAccess(
280 css::uno::Any
const & any
)
282 auto opt
= tryAccess
<T
>(any
);
284 throw css::uno::RuntimeException(
286 cppu_Any_extraction_failure_msg(
287 &any
, cppu::UnoType
<T
>::get().getTypeLibType()),
293 /** Access the value of a specific type stored in an Any, knowing the Any
294 contains a value of a matching type.
296 @attention A proxy returned from this function must not outlive the
297 corresponding Any passed into this function (as it may constitute a pointer
298 into the Any's internals). However, unlike with tryAccess, the benefit of
299 allowing this function to operate on temporaries appears to outweigh its
302 @note Ideally this would be a public member function of css::uno::Any. See
303 tryAccess for details.
305 @tparam T the C++ representation of a UNO type that can be contained in a
306 UNO ANY. See tryAccess for details.
308 @param any an Any value.
310 @return a positive proxy for the value of the specfied type obtained from
311 the given Any. See tryAccess for details.
313 template<typename T
> inline typename
detail::Optional
<T
>::type
forceAccess(
314 css::uno::Any
const & any
)
316 auto opt
= tryAccess
<T
>(any
);
325 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */