summaryrefslogtreecommitdiff
path: root/chromium/base/win/variant_util.h
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/base/win/variant_util.h')
-rw-r--r--chromium/base/win/variant_util.h151
1 files changed, 151 insertions, 0 deletions
diff --git a/chromium/base/win/variant_util.h b/chromium/base/win/variant_util.h
new file mode 100644
index 00000000000..24f60e58c63
--- /dev/null
+++ b/chromium/base/win/variant_util.h
@@ -0,0 +1,151 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_WIN_VARIANT_UTIL_H_
+#define BASE_WIN_VARIANT_UTIL_H_
+
+#include "base/logging.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;
+};
+
+// VariantUtil contains the underlying |Type| and helper methods
+// related to the |ElementVartype| for simple types.
+template <VARTYPE ElementVartype>
+struct VariantUtil 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_UTIL_H_