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