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