| // Copyright 2019 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef BASE_WIN_WINRT_FOUNDATION_HELPERS_H_ |
| #define BASE_WIN_WINRT_FOUNDATION_HELPERS_H_ |
| |
| #include <windows.foundation.h> |
| #include <wrl/client.h> |
| |
| #include <algorithm> |
| #include <vector> |
| |
| #include "base/check.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| |
| // This file provides helpers for WinRT types. |
| |
| namespace base::win::internal { |
| |
| // Template tricks needed to dispatch to the correct implementation. |
| // |
| // For all types which are neither InterfaceGroups nor RuntimeClasses, the |
| // following three typedefs are synonyms for a single C++ type. But for |
| // InterfaceGroups and RuntimeClasses, they are different types: |
| // LogicalT: The C++ Type for the InterfaceGroup or RuntimeClass, when |
| // used as a template parameter. Eg "RCFoo*" |
| // AbiT: The C++ type for the default interface used to represent the |
| // InterfaceGroup or RuntimeClass when passed as a method parameter. |
| // Eg "IFoo*" |
| // ComplexT: An instantiation of the Internal "AggregateType" template that |
| // combines LogicalT with AbiT. Eg "AggregateType<RCFoo*,IFoo*>". |
| // ComplexT is tightly coupled to the interface being implemented, |
| // hence defined in headers which include this file. |
| // For instance base/win/async_operation.h or |
| // base/win/collection_helpers.h |
| // |
| // windows.foundation.collections.h defines the following template and |
| // semantics in Windows::Foundation::Internal: |
| // |
| // template <class LogicalType, class AbiType> |
| // struct AggregateType; |
| // |
| // LogicalType - the Windows Runtime type (eg, runtime class, interface group, |
| // etc) being provided as an argument to an _impl template, when |
| // that type cannot be represented at the ABI. |
| // AbiType - the type used for marshalling, ie "at the ABI", for the |
| // logical type. |
| template <typename TComplex> |
| using AbiType = |
| typename ABI::Windows::Foundation::Internal::GetAbiType<TComplex>::type; |
| |
| template <typename TComplex> |
| using LogicalType = |
| typename ABI::Windows::Foundation::Internal::GetLogicalType<TComplex>::type; |
| |
| // Compile time switch to decide what container to use for |TComplex|. |
| // Depends on whether the underlying Abi type is a pointer to IUnknown or not. |
| // It queries the internals of Windows::Foundation to obtain this information. |
| template <typename TComplex> |
| using StorageType = std::conditional_t< |
| std::is_convertible<AbiType<TComplex>, IUnknown*>::value, |
| Microsoft::WRL::ComPtr<std::remove_pointer_t<AbiType<TComplex>>>, |
| AbiType<TComplex>>; |
| |
| // Similar to StorageType, but returns a absl::optional in case underlying Abi |
| // type is not a pointer to IUnknown. |
| template <typename TComplex> |
| using OptionalStorageType = std::conditional_t< |
| std::is_convertible<AbiType<TComplex>, IUnknown*>::value, |
| Microsoft::WRL::ComPtr<std::remove_pointer_t<AbiType<TComplex>>>, |
| absl::optional<AbiType<TComplex>>>; |
| |
| template <typename T> |
| HRESULT CopyTo(const T& value, T* ptr) { |
| *ptr = value; |
| return S_OK; |
| } |
| |
| template <typename T> |
| HRESULT CopyTo(const Microsoft::WRL::ComPtr<T>& value, T** ptr) { |
| return value.CopyTo(ptr); |
| } |
| |
| template <typename T> |
| HRESULT CopyTo(const absl::optional<T>& value, T* ptr) { |
| *ptr = *value; |
| return S_OK; |
| } |
| |
| template <typename T> |
| HRESULT CopyN(typename std::vector<T>::const_iterator first, |
| unsigned count, |
| T* result) { |
| std::copy_n(first, count, result); |
| return S_OK; |
| } |
| |
| template <typename T> |
| HRESULT CopyN( |
| typename std::vector<Microsoft::WRL::ComPtr<T>>::const_iterator first, |
| unsigned count, |
| T** result) { |
| for (unsigned i = 0; i < count; ++i) { |
| CopyTo(*first++, result++); |
| } |
| return S_OK; |
| } |
| |
| inline bool IsEqual(const HSTRING& lhs, const HSTRING& rhs) { |
| INT32 result; |
| HRESULT hr = ::WindowsCompareStringOrdinal(lhs, rhs, &result); |
| DCHECK(SUCCEEDED(hr)); |
| return result == 0; |
| } |
| |
| template <typename T> |
| bool IsEqual(const T& lhs, const T& rhs) { |
| return lhs == rhs; |
| } |
| |
| template <typename T> |
| bool IsEqual(const Microsoft::WRL::ComPtr<T>& com_ptr, const T* ptr) { |
| return com_ptr.Get() == ptr; |
| } |
| |
| struct Less { |
| bool operator()(const HSTRING& lhs, const HSTRING& rhs) const { |
| INT32 result; |
| HRESULT hr = ::WindowsCompareStringOrdinal(lhs, rhs, &result); |
| DCHECK(SUCCEEDED(hr)); |
| return result < 0; |
| } |
| |
| template <typename T> |
| bool operator()(const Microsoft::WRL::ComPtr<T>& com_ptr, |
| const T* ptr) const { |
| return com_ptr.Get() < ptr; |
| } |
| |
| template <typename T> |
| constexpr bool operator()(const T& lhs, const T& rhs) const { |
| return lhs < rhs; |
| } |
| }; |
| |
| } // namespace base::win::internal |
| |
| #endif // BASE_WIN_WINRT_FOUNDATION_HELPERS_H_ |