1*6777b538SAndroid Build Coastguard Worker // Copyright 2020 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_WIN_VARIANT_CONVERSIONS_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_WIN_VARIANT_CONVERSIONS_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <oaidl.h> 9*6777b538SAndroid Build Coastguard Worker #include <stdint.h> 10*6777b538SAndroid Build Coastguard Worker #include <wtypes.h> 11*6777b538SAndroid Build Coastguard Worker 12*6777b538SAndroid Build Coastguard Worker #include "base/check.h" 13*6777b538SAndroid Build Coastguard Worker 14*6777b538SAndroid Build Coastguard Worker namespace base { 15*6777b538SAndroid Build Coastguard Worker namespace win { 16*6777b538SAndroid Build Coastguard Worker namespace internal { 17*6777b538SAndroid Build Coastguard Worker 18*6777b538SAndroid Build Coastguard Worker // Returns true if a VARIANT of type |self| can be assigned to a 19*6777b538SAndroid Build Coastguard Worker // variant of type |other|. 20*6777b538SAndroid Build Coastguard Worker // Does not allow converting unsigned <-> signed or converting between 21*6777b538SAndroid Build Coastguard Worker // different sized types, but does allow converting IDispatch* -> IUnknown*. VarTypeIsConvertibleTo(VARTYPE self,VARTYPE other)22*6777b538SAndroid Build Coastguard Workerconstexpr bool VarTypeIsConvertibleTo(VARTYPE self, VARTYPE other) { 23*6777b538SAndroid Build Coastguard Worker // IDispatch inherits from IUnknown, so it's safe to 24*6777b538SAndroid Build Coastguard Worker // upcast a VT_DISPATCH into an IUnknown*. 25*6777b538SAndroid Build Coastguard Worker return (self == other) || (self == VT_DISPATCH && other == VT_UNKNOWN); 26*6777b538SAndroid Build Coastguard Worker } 27*6777b538SAndroid Build Coastguard Worker 28*6777b538SAndroid Build Coastguard Worker // VartypeToNativeType contains the underlying |Type| and offset to the 29*6777b538SAndroid Build Coastguard Worker // VARIANT union member related to the |ElementVartype| for simple types. 30*6777b538SAndroid Build Coastguard Worker template <VARTYPE ElementVartype> 31*6777b538SAndroid Build Coastguard Worker struct VartypeToNativeType final {}; 32*6777b538SAndroid Build Coastguard Worker 33*6777b538SAndroid Build Coastguard Worker template <> 34*6777b538SAndroid Build Coastguard Worker struct VartypeToNativeType<VT_BOOL> final { 35*6777b538SAndroid Build Coastguard Worker using Type = VARIANT_BOOL; 36*6777b538SAndroid Build Coastguard Worker static constexpr VARIANT_BOOL VARIANT::*kMemberOffset = &VARIANT::boolVal; 37*6777b538SAndroid Build Coastguard Worker }; 38*6777b538SAndroid Build Coastguard Worker 39*6777b538SAndroid Build Coastguard Worker template <> 40*6777b538SAndroid Build Coastguard Worker struct VartypeToNativeType<VT_I1> final { 41*6777b538SAndroid Build Coastguard Worker using Type = int8_t; 42*6777b538SAndroid Build Coastguard Worker static constexpr CHAR VARIANT::*kMemberOffset = &VARIANT::cVal; 43*6777b538SAndroid Build Coastguard Worker }; 44*6777b538SAndroid Build Coastguard Worker 45*6777b538SAndroid Build Coastguard Worker template <> 46*6777b538SAndroid Build Coastguard Worker struct VartypeToNativeType<VT_UI1> final { 47*6777b538SAndroid Build Coastguard Worker using Type = uint8_t; 48*6777b538SAndroid Build Coastguard Worker static constexpr BYTE VARIANT::*kMemberOffset = &VARIANT::bVal; 49*6777b538SAndroid Build Coastguard Worker }; 50*6777b538SAndroid Build Coastguard Worker 51*6777b538SAndroid Build Coastguard Worker template <> 52*6777b538SAndroid Build Coastguard Worker struct VartypeToNativeType<VT_I2> final { 53*6777b538SAndroid Build Coastguard Worker using Type = int16_t; 54*6777b538SAndroid Build Coastguard Worker static constexpr SHORT VARIANT::*kMemberOffset = &VARIANT::iVal; 55*6777b538SAndroid Build Coastguard Worker }; 56*6777b538SAndroid Build Coastguard Worker 57*6777b538SAndroid Build Coastguard Worker template <> 58*6777b538SAndroid Build Coastguard Worker struct VartypeToNativeType<VT_UI2> final { 59*6777b538SAndroid Build Coastguard Worker using Type = uint16_t; 60*6777b538SAndroid Build Coastguard Worker static constexpr USHORT VARIANT::*kMemberOffset = &VARIANT::uiVal; 61*6777b538SAndroid Build Coastguard Worker }; 62*6777b538SAndroid Build Coastguard Worker 63*6777b538SAndroid Build Coastguard Worker template <> 64*6777b538SAndroid Build Coastguard Worker struct VartypeToNativeType<VT_I4> final { 65*6777b538SAndroid Build Coastguard Worker using Type = int32_t; 66*6777b538SAndroid Build Coastguard Worker static constexpr LONG VARIANT::*kMemberOffset = &VARIANT::lVal; 67*6777b538SAndroid Build Coastguard Worker }; 68*6777b538SAndroid Build Coastguard Worker 69*6777b538SAndroid Build Coastguard Worker template <> 70*6777b538SAndroid Build Coastguard Worker struct VartypeToNativeType<VT_UI4> final { 71*6777b538SAndroid Build Coastguard Worker using Type = uint32_t; 72*6777b538SAndroid Build Coastguard Worker static constexpr ULONG VARIANT::*kMemberOffset = &VARIANT::ulVal; 73*6777b538SAndroid Build Coastguard Worker }; 74*6777b538SAndroid Build Coastguard Worker 75*6777b538SAndroid Build Coastguard Worker template <> 76*6777b538SAndroid Build Coastguard Worker struct VartypeToNativeType<VT_I8> final { 77*6777b538SAndroid Build Coastguard Worker using Type = int64_t; 78*6777b538SAndroid Build Coastguard Worker static constexpr LONGLONG VARIANT::*kMemberOffset = &VARIANT::llVal; 79*6777b538SAndroid Build Coastguard Worker }; 80*6777b538SAndroid Build Coastguard Worker 81*6777b538SAndroid Build Coastguard Worker template <> 82*6777b538SAndroid Build Coastguard Worker struct VartypeToNativeType<VT_UI8> final { 83*6777b538SAndroid Build Coastguard Worker using Type = uint64_t; 84*6777b538SAndroid Build Coastguard Worker static constexpr ULONGLONG VARIANT::*kMemberOffset = &VARIANT::ullVal; 85*6777b538SAndroid Build Coastguard Worker }; 86*6777b538SAndroid Build Coastguard Worker 87*6777b538SAndroid Build Coastguard Worker template <> 88*6777b538SAndroid Build Coastguard Worker struct VartypeToNativeType<VT_R4> final { 89*6777b538SAndroid Build Coastguard Worker using Type = float; 90*6777b538SAndroid Build Coastguard Worker static constexpr FLOAT VARIANT::*kMemberOffset = &VARIANT::fltVal; 91*6777b538SAndroid Build Coastguard Worker }; 92*6777b538SAndroid Build Coastguard Worker 93*6777b538SAndroid Build Coastguard Worker template <> 94*6777b538SAndroid Build Coastguard Worker struct VartypeToNativeType<VT_R8> final { 95*6777b538SAndroid Build Coastguard Worker using Type = double; 96*6777b538SAndroid Build Coastguard Worker static constexpr DOUBLE VARIANT::*kMemberOffset = &VARIANT::dblVal; 97*6777b538SAndroid Build Coastguard Worker }; 98*6777b538SAndroid Build Coastguard Worker 99*6777b538SAndroid Build Coastguard Worker template <> 100*6777b538SAndroid Build Coastguard Worker struct VartypeToNativeType<VT_DATE> final { 101*6777b538SAndroid Build Coastguard Worker using Type = DATE; 102*6777b538SAndroid Build Coastguard Worker static constexpr DATE VARIANT::*kMemberOffset = &VARIANT::date; 103*6777b538SAndroid Build Coastguard Worker }; 104*6777b538SAndroid Build Coastguard Worker 105*6777b538SAndroid Build Coastguard Worker template <> 106*6777b538SAndroid Build Coastguard Worker struct VartypeToNativeType<VT_BSTR> final { 107*6777b538SAndroid Build Coastguard Worker using Type = BSTR; 108*6777b538SAndroid Build Coastguard Worker static constexpr BSTR VARIANT::*kMemberOffset = &VARIANT::bstrVal; 109*6777b538SAndroid Build Coastguard Worker }; 110*6777b538SAndroid Build Coastguard Worker 111*6777b538SAndroid Build Coastguard Worker template <> 112*6777b538SAndroid Build Coastguard Worker struct VartypeToNativeType<VT_UNKNOWN> final { 113*6777b538SAndroid Build Coastguard Worker using Type = IUnknown*; 114*6777b538SAndroid Build Coastguard Worker static constexpr IUnknown* VARIANT::*kMemberOffset = &VARIANT::punkVal; 115*6777b538SAndroid Build Coastguard Worker }; 116*6777b538SAndroid Build Coastguard Worker 117*6777b538SAndroid Build Coastguard Worker template <> 118*6777b538SAndroid Build Coastguard Worker struct VartypeToNativeType<VT_DISPATCH> final { 119*6777b538SAndroid Build Coastguard Worker using Type = IDispatch*; 120*6777b538SAndroid Build Coastguard Worker static constexpr IDispatch* VARIANT::*kMemberOffset = &VARIANT::pdispVal; 121*6777b538SAndroid Build Coastguard Worker }; 122*6777b538SAndroid Build Coastguard Worker 123*6777b538SAndroid Build Coastguard Worker // VariantConverter contains the underlying |Type| and helper methods 124*6777b538SAndroid Build Coastguard Worker // related to the |ElementVartype| for simple types. 125*6777b538SAndroid Build Coastguard Worker template <VARTYPE ElementVartype> 126*6777b538SAndroid Build Coastguard Worker struct VariantConverter final { 127*6777b538SAndroid Build Coastguard Worker using Type = typename VartypeToNativeType<ElementVartype>::Type; 128*6777b538SAndroid Build Coastguard Worker static constexpr bool IsConvertibleTo(VARTYPE vartype) { 129*6777b538SAndroid Build Coastguard Worker return VarTypeIsConvertibleTo(ElementVartype, vartype); 130*6777b538SAndroid Build Coastguard Worker } 131*6777b538SAndroid Build Coastguard Worker static constexpr bool IsConvertibleFrom(VARTYPE vartype) { 132*6777b538SAndroid Build Coastguard Worker return VarTypeIsConvertibleTo(vartype, ElementVartype); 133*6777b538SAndroid Build Coastguard Worker } 134*6777b538SAndroid Build Coastguard Worker // Get the associated VARIANT union member value. 135*6777b538SAndroid Build Coastguard Worker // Returns the value owned by the VARIANT without affecting the lifetime 136*6777b538SAndroid Build Coastguard Worker // of managed contents. 137*6777b538SAndroid Build Coastguard Worker // e.g. Does not affect IUnknown* reference counts or allocate a BSTR. 138*6777b538SAndroid Build Coastguard Worker static Type RawGet(const VARIANT& var) { 139*6777b538SAndroid Build Coastguard Worker DCHECK(IsConvertibleFrom(V_VT(&var))); 140*6777b538SAndroid Build Coastguard Worker return var.*VartypeToNativeType<ElementVartype>::kMemberOffset; 141*6777b538SAndroid Build Coastguard Worker } 142*6777b538SAndroid Build Coastguard Worker // Set the associated VARIANT union member value. 143*6777b538SAndroid Build Coastguard Worker // The caller is responsible for handling the lifetime of managed contents. 144*6777b538SAndroid Build Coastguard Worker // e.g. Incrementing IUnknown* reference counts or allocating a BSTR. 145*6777b538SAndroid Build Coastguard Worker static void RawSet(VARIANT* var, Type value) { 146*6777b538SAndroid Build Coastguard Worker DCHECK(IsConvertibleTo(V_VT(var))); 147*6777b538SAndroid Build Coastguard Worker var->*VartypeToNativeType<ElementVartype>::kMemberOffset = value; 148*6777b538SAndroid Build Coastguard Worker } 149*6777b538SAndroid Build Coastguard Worker }; 150*6777b538SAndroid Build Coastguard Worker 151*6777b538SAndroid Build Coastguard Worker } // namespace internal 152*6777b538SAndroid Build Coastguard Worker } // namespace win 153*6777b538SAndroid Build Coastguard Worker } // namespace base 154*6777b538SAndroid Build Coastguard Worker 155*6777b538SAndroid Build Coastguard Worker #endif // BASE_WIN_VARIANT_CONVERSIONS_H_ 156