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