150 lines
4.8 KiB
C
150 lines
4.8 KiB
C
|
|
// 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_
|