Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / include / o3tl / any.hxx
blob85fd281064193e81c45e3c222100f6c27bd7f951
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #ifndef INCLUDED_O3TL_ANY_HXX
11 #define INCLUDED_O3TL_ANY_HXX
13 #include <sal/config.h>
15 #include <cassert>
16 #include <type_traits>
17 #include <utility>
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.
32 namespace o3tl {
34 namespace detail {
36 struct Void {};
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>>:
77 std::true_type
78 {};
79 template<> struct IsDerivedReference<css::uno::Reference<css::uno::XInterface>>:
80 std::false_type
81 {};
83 template<typename> struct IsUnoSequenceType: std::false_type {};
84 template<typename T> struct IsUnoSequenceType<cppu::UnoSequenceType<T>>:
85 std::true_type
86 {};
88 template<typename T> inline boost::optional<T const> tryGetConverted(
89 css::uno::Any const & any)
91 T v;
92 return (any >>= v)
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
115 avoid misuses like
116 @code
117 css::uno::Any f();
119 if (auto p = o3tl::tryAccess<css::beans::NamedValue>(f())) {
120 return p->Name;
122 @endcode
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
232 // be complete:
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
257 on failure.
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
263 dangers.
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
277 cannot be obtained.
279 template<typename T> inline typename detail::Optional<T>::type doAccess(
280 css::uno::Any const & any)
282 auto opt = tryAccess<T>(any);
283 if (!opt) {
284 throw css::uno::RuntimeException(
285 OUString(
286 cppu_Any_extraction_failure_msg(
287 &any, cppu::UnoType<T>::get().getTypeLibType()),
288 SAL_NO_ACQUIRE));
290 return opt;
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
300 dangers.
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);
317 assert(opt);
318 return opt;
323 #endif
325 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */