156 lines
4.6 KiB
C++
156 lines
4.6 KiB
C++
// Copyright 2020 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_VARIANT_CONVERSIONS_H_
|
|
#define BASE_WIN_VARIANT_CONVERSIONS_H_
|
|
|
|
#include <oaidl.h>
|
|
#include <stdint.h>
|
|
#include <wtypes.h>
|
|
|
|
#include "base/check.h"
|
|
|
|
namespace base {
|
|
namespace win {
|
|
namespace internal {
|
|
|
|
// Returns true if a VARIANT of type |self| can be assigned to a
|
|
// variant of type |other|.
|
|
// Does not allow converting unsigned <-> signed or converting between
|
|
// different sized types, but does allow converting IDispatch* -> IUnknown*.
|
|
constexpr bool VarTypeIsConvertibleTo(VARTYPE self, VARTYPE other) {
|
|
// IDispatch inherits from IUnknown, so it's safe to
|
|
// upcast a VT_DISPATCH into an IUnknown*.
|
|
return (self == other) || (self == VT_DISPATCH && other == VT_UNKNOWN);
|
|
}
|
|
|
|
// VartypeToNativeType contains the underlying |Type| and offset to the
|
|
// VARIANT union member related to the |ElementVartype| for simple types.
|
|
template <VARTYPE ElementVartype>
|
|
struct VartypeToNativeType final {};
|
|
|
|
template <>
|
|
struct VartypeToNativeType<VT_BOOL> final {
|
|
using Type = VARIANT_BOOL;
|
|
static constexpr VARIANT_BOOL VARIANT::*kMemberOffset = &VARIANT::boolVal;
|
|
};
|
|
|
|
template <>
|
|
struct VartypeToNativeType<VT_I1> final {
|
|
using Type = int8_t;
|
|
static constexpr CHAR VARIANT::*kMemberOffset = &VARIANT::cVal;
|
|
};
|
|
|
|
template <>
|
|
struct VartypeToNativeType<VT_UI1> final {
|
|
using Type = uint8_t;
|
|
static constexpr BYTE VARIANT::*kMemberOffset = &VARIANT::bVal;
|
|
};
|
|
|
|
template <>
|
|
struct VartypeToNativeType<VT_I2> final {
|
|
using Type = int16_t;
|
|
static constexpr SHORT VARIANT::*kMemberOffset = &VARIANT::iVal;
|
|
};
|
|
|
|
template <>
|
|
struct VartypeToNativeType<VT_UI2> final {
|
|
using Type = uint16_t;
|
|
static constexpr USHORT VARIANT::*kMemberOffset = &VARIANT::uiVal;
|
|
};
|
|
|
|
template <>
|
|
struct VartypeToNativeType<VT_I4> final {
|
|
using Type = int32_t;
|
|
static constexpr LONG VARIANT::*kMemberOffset = &VARIANT::lVal;
|
|
};
|
|
|
|
template <>
|
|
struct VartypeToNativeType<VT_UI4> final {
|
|
using Type = uint32_t;
|
|
static constexpr ULONG VARIANT::*kMemberOffset = &VARIANT::ulVal;
|
|
};
|
|
|
|
template <>
|
|
struct VartypeToNativeType<VT_I8> final {
|
|
using Type = int64_t;
|
|
static constexpr LONGLONG VARIANT::*kMemberOffset = &VARIANT::llVal;
|
|
};
|
|
|
|
template <>
|
|
struct VartypeToNativeType<VT_UI8> final {
|
|
using Type = uint64_t;
|
|
static constexpr ULONGLONG VARIANT::*kMemberOffset = &VARIANT::ullVal;
|
|
};
|
|
|
|
template <>
|
|
struct VartypeToNativeType<VT_R4> final {
|
|
using Type = float;
|
|
static constexpr FLOAT VARIANT::*kMemberOffset = &VARIANT::fltVal;
|
|
};
|
|
|
|
template <>
|
|
struct VartypeToNativeType<VT_R8> final {
|
|
using Type = double;
|
|
static constexpr DOUBLE VARIANT::*kMemberOffset = &VARIANT::dblVal;
|
|
};
|
|
|
|
template <>
|
|
struct VartypeToNativeType<VT_DATE> final {
|
|
using Type = DATE;
|
|
static constexpr DATE VARIANT::*kMemberOffset = &VARIANT::date;
|
|
};
|
|
|
|
template <>
|
|
struct VartypeToNativeType<VT_BSTR> final {
|
|
using Type = BSTR;
|
|
static constexpr BSTR VARIANT::*kMemberOffset = &VARIANT::bstrVal;
|
|
};
|
|
|
|
template <>
|
|
struct VartypeToNativeType<VT_UNKNOWN> final {
|
|
using Type = IUnknown*;
|
|
static constexpr IUnknown* VARIANT::*kMemberOffset = &VARIANT::punkVal;
|
|
};
|
|
|
|
template <>
|
|
struct VartypeToNativeType<VT_DISPATCH> final {
|
|
using Type = IDispatch*;
|
|
static constexpr IDispatch* VARIANT::*kMemberOffset = &VARIANT::pdispVal;
|
|
};
|
|
|
|
// VariantConverter contains the underlying |Type| and helper methods
|
|
// related to the |ElementVartype| for simple types.
|
|
template <VARTYPE ElementVartype>
|
|
struct VariantConverter final {
|
|
using Type = typename VartypeToNativeType<ElementVartype>::Type;
|
|
static constexpr bool IsConvertibleTo(VARTYPE vartype) {
|
|
return VarTypeIsConvertibleTo(ElementVartype, vartype);
|
|
}
|
|
static constexpr bool IsConvertibleFrom(VARTYPE vartype) {
|
|
return VarTypeIsConvertibleTo(vartype, ElementVartype);
|
|
}
|
|
// Get the associated VARIANT union member value.
|
|
// Returns the value owned by the VARIANT without affecting the lifetime
|
|
// of managed contents.
|
|
// e.g. Does not affect IUnknown* reference counts or allocate a BSTR.
|
|
static Type RawGet(const VARIANT& var) {
|
|
DCHECK(IsConvertibleFrom(V_VT(&var)));
|
|
return var.*VartypeToNativeType<ElementVartype>::kMemberOffset;
|
|
}
|
|
// Set the associated VARIANT union member value.
|
|
// The caller is responsible for handling the lifetime of managed contents.
|
|
// e.g. Incrementing IUnknown* reference counts or allocating a BSTR.
|
|
static void RawSet(VARIANT* var, Type value) {
|
|
DCHECK(IsConvertibleTo(V_VT(var)));
|
|
var->*VartypeToNativeType<ElementVartype>::kMemberOffset = value;
|
|
}
|
|
};
|
|
|
|
} // namespace internal
|
|
} // namespace win
|
|
} // namespace base
|
|
|
|
#endif // BASE_WIN_VARIANT_CONVERSIONS_H_
|