1 // Copyright 2020 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_WIN_VARIANT_VECTOR_H_ 6 #define BASE_WIN_VARIANT_VECTOR_H_ 7 8 #include <objbase.h> 9 10 #include <oleauto.h> 11 12 #include <type_traits> 13 #include <utility> 14 #include <vector> 15 16 #include "base/base_export.h" 17 #include "base/check.h" 18 #include "base/logging.h" 19 #include "base/win/scoped_variant.h" 20 #include "base/win/variant_conversions.h" 21 22 namespace base { 23 namespace win { 24 25 // This class has RAII semantics and is used to build a vector for a specific 26 // OLE VARTYPE, and handles converting the data to a VARIANT or VARIANT 27 // SAFEARRAY. It can be populated similarly to a STL vector<T>, but without the 28 // compile-time requirement of knowing what element type the VariantVector will 29 // store. The VariantVector only allows one variant type to be stored at a time. 30 // 31 // This class can release ownership of its contents to a VARIANT, and will 32 // automatically allocate + populate a SAFEARRAY as needed or when explicitly 33 // requesting that the results be released as a SAFEARRAY. 34 class BASE_EXPORT VariantVector final { 35 public: 36 VariantVector(); 37 VariantVector(VariantVector&& other); 38 VariantVector& operator=(VariantVector&& other); 39 VariantVector(const VariantVector&) = delete; 40 VariantVector& operator=(const VariantVector&) = delete; 41 ~VariantVector(); 42 43 bool operator==(const VariantVector& other) const; 44 bool operator!=(const VariantVector& other) const; 45 46 // Returns the variant type for data stored in the VariantVector. Type()47 VARTYPE Type() const { return vartype_; } 48 49 // Returns the number of elements in the VariantVector. Size()50 size_t Size() const { return vector_.size(); } 51 52 // Returns whether or not there are any elements. Empty()53 bool Empty() const { return vector_.empty(); } 54 55 // Resets VariantVector to its default state, releasing any managed content. 56 void Reset(); 57 58 // Helper template method for selecting the correct |Insert| call based 59 // on the underlying type that is expected for a VARTYPE. 60 template <VARTYPE ExpectedVartype, 61 std::enable_if_t<ExpectedVartype != VT_BOOL, int> = 0> Insert(typename internal::VariantConverter<ExpectedVartype>::Type value)62 void Insert( 63 typename internal::VariantConverter<ExpectedVartype>::Type value) { 64 if (vartype_ == VT_EMPTY) 65 vartype_ = ExpectedVartype; 66 AssertVartype<ExpectedVartype>(); 67 ScopedVariant scoped_variant; 68 scoped_variant.Set(value); 69 vector_.push_back(std::move(scoped_variant)); 70 } 71 72 // Specialize VT_BOOL to accept a bool type instead of VARIANT_BOOL, 73 // this is to make calling insert with VT_BOOL safer. 74 template <VARTYPE ExpectedVartype, 75 std::enable_if_t<ExpectedVartype == VT_BOOL, int> = 0> Insert(bool value)76 void Insert(bool value) { 77 if (vartype_ == VT_EMPTY) 78 vartype_ = ExpectedVartype; 79 AssertVartype<ExpectedVartype>(); 80 ScopedVariant scoped_variant; 81 scoped_variant.Set(value); 82 vector_.push_back(std::move(scoped_variant)); 83 } 84 85 // Specialize VT_DATE because ScopedVariant has a separate SetDate method, 86 // this is because VT_R8 and VT_DATE share the same underlying type. 87 template <> 88 void Insert<VT_DATE>( 89 typename internal::VariantConverter<VT_DATE>::Type value) { 90 if (vartype_ == VT_EMPTY) 91 vartype_ = VT_DATE; 92 AssertVartype<VT_DATE>(); 93 ScopedVariant scoped_variant; 94 scoped_variant.SetDate(value); 95 vector_.push_back(std::move(scoped_variant)); 96 } 97 98 // Populates a VARIANT based on what is stored, transferring ownership 99 // of managed contents. 100 // This is only valid when the VariantVector is empty or has a single element. 101 // The VariantVector is then reset. 102 VARIANT ReleaseAsScalarVariant(); 103 104 // Populates a VARIANT as a SAFEARRAY, even if there is only one element. 105 // The VariantVector is then reset. 106 VARIANT ReleaseAsSafearrayVariant(); 107 108 // Lexicographical comparison between a VariantVector and a VARIANT. 109 // The return value is 0 if the variants are equal, 1 if this object is 110 // greater than |other|, -1 if it is smaller. 111 int Compare(const VARIANT& other, bool ignore_case = false) const; 112 113 // Lexicographical comparison between a VariantVector and a SAFEARRAY. 114 int Compare(SAFEARRAY* safearray, bool ignore_case = false) const; 115 116 // Lexicographical comparison between two VariantVectors. 117 int Compare(const VariantVector& other, bool ignore_case = false) const; 118 119 private: 120 // Returns true if the current |vartype_| is compatible with |ExpectedVartype| 121 // for inserting into |vector_|. 122 template <VARTYPE ExpectedVartype> AssertVartype()123 void AssertVartype() const { 124 DCHECK( 125 internal::VariantConverter<ExpectedVartype>::IsConvertibleTo(vartype_)) 126 << "Type mismatch, " << ExpectedVartype << " is not convertible to " 127 << Type(); 128 } 129 130 // Creates a SAFEARRAY and populates it with teh values held by each VARIANT 131 // in |vector_|, transferring ownership to the new SAFEARRAY. 132 // The VariantVector is reset when successful. 133 template <VARTYPE ElementVartype> 134 SAFEARRAY* CreateAndPopulateSafearray(); 135 136 VARTYPE vartype_ = VT_EMPTY; 137 std::vector<ScopedVariant> vector_; 138 }; 139 140 } // namespace win 141 } // namespace base 142 143 #endif // BASE_WIN_VARIANT_VECTOR_H_ 144