variant_util.h 4.7 KB

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