xref: /aosp_15_r20/external/cronet/base/win/variant_vector.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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