/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_O3TL_ANY_HXX #define INCLUDED_O3TL_ANY_HXX #include #include #include #include #include #include #include #include #include #include #include #include // Some functionality related to css::uno::Any that would ideally be part of // , but (for now) cannot be for some reason. namespace o3tl { namespace detail { struct Void {}; template struct Optional { using type = T const *; }; template<> struct Optional { using type = std::optional; }; template<> struct Optional { using type = std::optional; }; template<> struct Optional { using type = std::optional; }; template<> struct Optional { using type = std::optional; }; template<> struct Optional { using type = std::optional; }; template<> struct Optional { using type = std::optional; }; template<> struct Optional { using type = std::optional; }; template<> struct Optional { using type = std::optional; }; template<> struct Optional { using type = std::optional; }; template<> struct Optional { using type = std::optional; }; template<> struct Optional { using type = std::optional; }; template struct Optional> { using type = std::optional const>; }; template<> struct Optional> { using type = css::uno::Reference const *; }; template struct IsDerivedReference: std::false_type {}; template struct IsDerivedReference>: std::true_type {}; template<> struct IsDerivedReference>: std::false_type {}; template struct IsUnoSequenceType: std::false_type {}; template struct IsUnoSequenceType>: std::true_type {}; template inline std::optional tryGetConverted( css::uno::Any const & any) { T v; return (any >>= v) ? std::optional(std::move(v)) : std::optional(); } } /** Try to access the value of a specific type stored in an Any. In trying to obtain a value, the same set of conversions as supported by ">>=" are considered. The returned object is a proxy. Proxies can be either positive or negative. Each proxy can be contextually converted to bool, yielding true iff the proxy is positive. For a positive proxy P representing a value of requested type T, for any T other than void, the expression *P yields that value of type T. (Technically, the proxy is either a plain pointer or a std::optional, depending on whether a plain pointer into the given Any can be returned for the specified type.) @attention A proxy returned from this function must not outlive the corresponding Any passed into this function (as it may constitute a pointer into the Any's internals). That is the reason why this function is restricted to lvalue arguments (i.e., to non-temporary Any objects), to avoid misuses like @code css::uno::Any f(); if (auto p = o3tl::tryAccess(f())) { return p->Name; } @endcode @note Ideally this would be a public member function of css::uno::Any (at least conditional on LIBO_INTERNAL_ONLY, as it requires C++11). However, as std::optional (which would be needed to implement the proxies) is only available since C++14, we need to use std::optional for now. But To not make every entity that includes depend on boost_headers, keep this here for now. @tparam T the C++ representation of a UNO type that can be contained in a UNO ANY (i.e., any UNO type other than ANY itself). The legacy C++ representations sal_Bool, cppu::UnoVoidType, cppu::UnoUnsignedShortType, cppu::UnoCharType, and cppu::UnoSequenceType are not supported. Must be a complete type or void. @param any an Any value. @return a positive proxy for the value of the specified type obtained from the given Any, or a negative proxy if no such value can be obtained. */ template inline typename std::enable_if< !(detail::IsDerivedReference::value || detail::IsUnoSequenceType::value || std::is_base_of::value), typename detail::Optional::type>::type tryAccess(css::uno::Any const & any) { // CHAR, STRING, TYPE, sequence types, enum types, struct types, exception // types, and com.sun.star.uno.XInterface interface type: return cppu::UnoType::get().isAssignableFrom(any.getValueType()) ? static_cast(any.getValue()) : nullptr; } template<> inline detail::Optional::type tryAccess( css::uno::Any const & any) { return any.hasValue() ? std::optional() : std::optional(detail::Void()); } template<> inline detail::Optional::type tryAccess( css::uno::Any const & any) { return detail::tryGetConverted(any); } template<> inline detail::Optional::type tryAccess( css::uno::Any const & any) { return detail::tryGetConverted(any); } template<> inline detail::Optional::type tryAccess( css::uno::Any const & any) { return detail::tryGetConverted(any); } template<> inline detail::Optional::type tryAccess( css::uno::Any const & any) { return detail::tryGetConverted(any); } template<> inline detail::Optional::type tryAccess( css::uno::Any const & any) { return detail::tryGetConverted(any); } template<> inline detail::Optional::type tryAccess( css::uno::Any const & any) { return detail::tryGetConverted(any); } template<> inline detail::Optional::type tryAccess( css::uno::Any const & any) { return detail::tryGetConverted(any); } template<> inline detail::Optional::type tryAccess( css::uno::Any const & any) { return detail::tryGetConverted(any); } template<> inline detail::Optional::type tryAccess( css::uno::Any const & any) { return detail::tryGetConverted(any); } template<> inline detail::Optional::type tryAccess( css::uno::Any const & any) { return detail::tryGetConverted(any); } template<> detail::Optional::type tryAccess( css::uno::Any const &) = delete; template<> detail::Optional::type tryAccess( css::uno::Any const &) = delete; /* // Already prevented by std::is_base_of requiring T to // be complete: template<> detail::Optional::type tryAccess(css::uno::Any const &) = delete; template<> detail::Optional::type tryAccess(css::uno::Any const &) = delete; template<> detail::Optional::type tryAccess(css::uno::Any const &) = delete; */ template inline typename std::enable_if< detail::IsDerivedReference::value, typename detail::Optional::type>::type tryAccess(css::uno::Any const & any) { return detail::tryGetConverted(any); } template typename detail::Optional::type tryAccess( css::uno::Any const volatile &&) = delete; /** Access the value of a specific type stored in an Any, throwing an exception on failure. @attention A proxy returned from this function must not outlive the corresponding Any passed into this function (as it may constitute a pointer into the Any's internals). However, unlike with tryAccess, the benefit of allowing this function to operate on temporaries appears to outweigh its dangers. @note Ideally this would be a public member function of css::uno::Any. See tryAccess for details. @tparam T the C++ representation of a UNO type that can be contained in a UNO ANY. See tryAccess for details. @param any an Any value. @return a positive proxy for the value of the specified type obtained from the given Any. See tryAccess for details. @throws css::uno::RuntimeException when a value of the requested type cannot be obtained. */ template inline typename detail::Optional::type doAccess( css::uno::Any const & any) { auto opt = tryAccess(any); if (!opt) { throw css::uno::RuntimeException( OUString( cppu_Any_extraction_failure_msg( &any, cppu::UnoType::get().getTypeLibType()), SAL_NO_ACQUIRE)); } return opt; } /** Access the value of a specific type stored in an Any, knowing the Any contains a value of a matching type. @attention A proxy returned from this function must not outlive the corresponding Any passed into this function (as it may constitute a pointer into the Any's internals). However, unlike with tryAccess, the benefit of allowing this function to operate on temporaries appears to outweigh its dangers. @note Ideally this would be a public member function of css::uno::Any. See tryAccess for details. @tparam T the C++ representation of a UNO type that can be contained in a UNO ANY. See tryAccess for details. @param any an Any value. @return a positive proxy for the value of the specified type obtained from the given Any. See tryAccess for details. */ template inline typename detail::Optional::type forceAccess( css::uno::Any const & any) { auto opt = tryAccess(any); assert(opt); return opt; } } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */