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 #include "base/win/variant_vector.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <optional>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/numerics/checked_math.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/process/memory.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/win/scoped_safearray.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/win/scoped_variant.h"
15*6777b538SAndroid Build Coastguard Worker
16*6777b538SAndroid Build Coastguard Worker namespace base {
17*6777b538SAndroid Build Coastguard Worker namespace win {
18*6777b538SAndroid Build Coastguard Worker
19*6777b538SAndroid Build Coastguard Worker namespace {
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker // Lexicographical comparison between the contents of |vector| and |safearray|.
22*6777b538SAndroid Build Coastguard Worker template <VARTYPE ElementVartype>
CompareAgainstSafearray(const std::vector<ScopedVariant> & vector,const ScopedSafearray & safearray,bool ignore_case)23*6777b538SAndroid Build Coastguard Worker int CompareAgainstSafearray(const std::vector<ScopedVariant>& vector,
24*6777b538SAndroid Build Coastguard Worker const ScopedSafearray& safearray,
25*6777b538SAndroid Build Coastguard Worker bool ignore_case) {
26*6777b538SAndroid Build Coastguard Worker std::optional<ScopedSafearray::LockScope<ElementVartype>> lock_scope =
27*6777b538SAndroid Build Coastguard Worker safearray.CreateLockScope<ElementVartype>();
28*6777b538SAndroid Build Coastguard Worker // If we fail to create a lock scope, then arbitrarily treat |this| as
29*6777b538SAndroid Build Coastguard Worker // greater. This should only happen when the SAFEARRAY fails to be locked,
30*6777b538SAndroid Build Coastguard Worker // so we cannot compare the contents of the SAFEARRAY.
31*6777b538SAndroid Build Coastguard Worker if (!lock_scope)
32*6777b538SAndroid Build Coastguard Worker return 1;
33*6777b538SAndroid Build Coastguard Worker
34*6777b538SAndroid Build Coastguard Worker // Create a temporary VARIANT which does not own its contents, and is
35*6777b538SAndroid Build Coastguard Worker // populated with values from the |lock_scope| so it can be compared against.
36*6777b538SAndroid Build Coastguard Worker VARIANT non_owning_temp;
37*6777b538SAndroid Build Coastguard Worker V_VT(&non_owning_temp) = ElementVartype;
38*6777b538SAndroid Build Coastguard Worker
39*6777b538SAndroid Build Coastguard Worker auto vector_iter = vector.begin();
40*6777b538SAndroid Build Coastguard Worker auto scope_iter = lock_scope->begin();
41*6777b538SAndroid Build Coastguard Worker for (; vector_iter != vector.end() && scope_iter != lock_scope->end();
42*6777b538SAndroid Build Coastguard Worker ++vector_iter, ++scope_iter) {
43*6777b538SAndroid Build Coastguard Worker internal::VariantConverter<ElementVartype>::RawSet(&non_owning_temp,
44*6777b538SAndroid Build Coastguard Worker *scope_iter);
45*6777b538SAndroid Build Coastguard Worker int compare_result = vector_iter->Compare(non_owning_temp, ignore_case);
46*6777b538SAndroid Build Coastguard Worker // If there is a difference in values, return the difference.
47*6777b538SAndroid Build Coastguard Worker if (compare_result)
48*6777b538SAndroid Build Coastguard Worker return compare_result;
49*6777b538SAndroid Build Coastguard Worker }
50*6777b538SAndroid Build Coastguard Worker // There are more elements in |vector|, so |vector| is
51*6777b538SAndroid Build Coastguard Worker // greater than |safearray|.
52*6777b538SAndroid Build Coastguard Worker if (vector_iter != vector.end())
53*6777b538SAndroid Build Coastguard Worker return 1;
54*6777b538SAndroid Build Coastguard Worker // There are more elements in |safearray|, so |vector| is
55*6777b538SAndroid Build Coastguard Worker // less than |safearray|.
56*6777b538SAndroid Build Coastguard Worker if (scope_iter != lock_scope->end())
57*6777b538SAndroid Build Coastguard Worker return -1;
58*6777b538SAndroid Build Coastguard Worker return 0;
59*6777b538SAndroid Build Coastguard Worker }
60*6777b538SAndroid Build Coastguard Worker
61*6777b538SAndroid Build Coastguard Worker } // namespace
62*6777b538SAndroid Build Coastguard Worker
63*6777b538SAndroid Build Coastguard Worker VariantVector::VariantVector() = default;
64*6777b538SAndroid Build Coastguard Worker
VariantVector(VariantVector && other)65*6777b538SAndroid Build Coastguard Worker VariantVector::VariantVector(VariantVector&& other)
66*6777b538SAndroid Build Coastguard Worker : vartype_(std::exchange(other.vartype_, VT_EMPTY)),
67*6777b538SAndroid Build Coastguard Worker vector_(std::move(other.vector_)) {}
68*6777b538SAndroid Build Coastguard Worker
operator =(VariantVector && other)69*6777b538SAndroid Build Coastguard Worker VariantVector& VariantVector::operator=(VariantVector&& other) {
70*6777b538SAndroid Build Coastguard Worker DCHECK_NE(this, &other);
71*6777b538SAndroid Build Coastguard Worker vartype_ = std::exchange(other.vartype_, VT_EMPTY);
72*6777b538SAndroid Build Coastguard Worker vector_ = std::move(other.vector_);
73*6777b538SAndroid Build Coastguard Worker return *this;
74*6777b538SAndroid Build Coastguard Worker }
75*6777b538SAndroid Build Coastguard Worker
~VariantVector()76*6777b538SAndroid Build Coastguard Worker VariantVector::~VariantVector() {
77*6777b538SAndroid Build Coastguard Worker Reset();
78*6777b538SAndroid Build Coastguard Worker }
79*6777b538SAndroid Build Coastguard Worker
operator ==(const VariantVector & other) const80*6777b538SAndroid Build Coastguard Worker bool VariantVector::operator==(const VariantVector& other) const {
81*6777b538SAndroid Build Coastguard Worker return !Compare(other);
82*6777b538SAndroid Build Coastguard Worker }
83*6777b538SAndroid Build Coastguard Worker
operator !=(const VariantVector & other) const84*6777b538SAndroid Build Coastguard Worker bool VariantVector::operator!=(const VariantVector& other) const {
85*6777b538SAndroid Build Coastguard Worker return !VariantVector::operator==(other);
86*6777b538SAndroid Build Coastguard Worker }
87*6777b538SAndroid Build Coastguard Worker
Reset()88*6777b538SAndroid Build Coastguard Worker void VariantVector::Reset() {
89*6777b538SAndroid Build Coastguard Worker vector_.clear();
90*6777b538SAndroid Build Coastguard Worker vartype_ = VT_EMPTY;
91*6777b538SAndroid Build Coastguard Worker }
92*6777b538SAndroid Build Coastguard Worker
ReleaseAsScalarVariant()93*6777b538SAndroid Build Coastguard Worker VARIANT VariantVector::ReleaseAsScalarVariant() {
94*6777b538SAndroid Build Coastguard Worker ScopedVariant scoped_variant;
95*6777b538SAndroid Build Coastguard Worker
96*6777b538SAndroid Build Coastguard Worker if (!Empty()) {
97*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(Size(), 1U);
98*6777b538SAndroid Build Coastguard Worker scoped_variant = std::move(vector_[0]);
99*6777b538SAndroid Build Coastguard Worker Reset();
100*6777b538SAndroid Build Coastguard Worker }
101*6777b538SAndroid Build Coastguard Worker
102*6777b538SAndroid Build Coastguard Worker return scoped_variant.Release();
103*6777b538SAndroid Build Coastguard Worker }
104*6777b538SAndroid Build Coastguard Worker
ReleaseAsSafearrayVariant()105*6777b538SAndroid Build Coastguard Worker VARIANT VariantVector::ReleaseAsSafearrayVariant() {
106*6777b538SAndroid Build Coastguard Worker ScopedVariant scoped_variant;
107*6777b538SAndroid Build Coastguard Worker
108*6777b538SAndroid Build Coastguard Worker switch (Type()) {
109*6777b538SAndroid Build Coastguard Worker case VT_EMPTY:
110*6777b538SAndroid Build Coastguard Worker break;
111*6777b538SAndroid Build Coastguard Worker case VT_BOOL:
112*6777b538SAndroid Build Coastguard Worker scoped_variant.Set(CreateAndPopulateSafearray<VT_BOOL>());
113*6777b538SAndroid Build Coastguard Worker break;
114*6777b538SAndroid Build Coastguard Worker case VT_I1:
115*6777b538SAndroid Build Coastguard Worker scoped_variant.Set(CreateAndPopulateSafearray<VT_I1>());
116*6777b538SAndroid Build Coastguard Worker break;
117*6777b538SAndroid Build Coastguard Worker case VT_UI1:
118*6777b538SAndroid Build Coastguard Worker scoped_variant.Set(CreateAndPopulateSafearray<VT_UI1>());
119*6777b538SAndroid Build Coastguard Worker break;
120*6777b538SAndroid Build Coastguard Worker case VT_I2:
121*6777b538SAndroid Build Coastguard Worker scoped_variant.Set(CreateAndPopulateSafearray<VT_I2>());
122*6777b538SAndroid Build Coastguard Worker break;
123*6777b538SAndroid Build Coastguard Worker case VT_UI2:
124*6777b538SAndroid Build Coastguard Worker scoped_variant.Set(CreateAndPopulateSafearray<VT_UI2>());
125*6777b538SAndroid Build Coastguard Worker break;
126*6777b538SAndroid Build Coastguard Worker case VT_I4:
127*6777b538SAndroid Build Coastguard Worker scoped_variant.Set(CreateAndPopulateSafearray<VT_I4>());
128*6777b538SAndroid Build Coastguard Worker break;
129*6777b538SAndroid Build Coastguard Worker case VT_UI4:
130*6777b538SAndroid Build Coastguard Worker scoped_variant.Set(CreateAndPopulateSafearray<VT_UI4>());
131*6777b538SAndroid Build Coastguard Worker break;
132*6777b538SAndroid Build Coastguard Worker case VT_I8:
133*6777b538SAndroid Build Coastguard Worker scoped_variant.Set(CreateAndPopulateSafearray<VT_I8>());
134*6777b538SAndroid Build Coastguard Worker break;
135*6777b538SAndroid Build Coastguard Worker case VT_UI8:
136*6777b538SAndroid Build Coastguard Worker scoped_variant.Set(CreateAndPopulateSafearray<VT_UI8>());
137*6777b538SAndroid Build Coastguard Worker break;
138*6777b538SAndroid Build Coastguard Worker case VT_R4:
139*6777b538SAndroid Build Coastguard Worker scoped_variant.Set(CreateAndPopulateSafearray<VT_R4>());
140*6777b538SAndroid Build Coastguard Worker break;
141*6777b538SAndroid Build Coastguard Worker case VT_R8:
142*6777b538SAndroid Build Coastguard Worker scoped_variant.Set(CreateAndPopulateSafearray<VT_R8>());
143*6777b538SAndroid Build Coastguard Worker break;
144*6777b538SAndroid Build Coastguard Worker case VT_DATE:
145*6777b538SAndroid Build Coastguard Worker scoped_variant.Set(CreateAndPopulateSafearray<VT_DATE>());
146*6777b538SAndroid Build Coastguard Worker break;
147*6777b538SAndroid Build Coastguard Worker case VT_BSTR:
148*6777b538SAndroid Build Coastguard Worker scoped_variant.Set(CreateAndPopulateSafearray<VT_BSTR>());
149*6777b538SAndroid Build Coastguard Worker break;
150*6777b538SAndroid Build Coastguard Worker case VT_DISPATCH:
151*6777b538SAndroid Build Coastguard Worker scoped_variant.Set(CreateAndPopulateSafearray<VT_DISPATCH>());
152*6777b538SAndroid Build Coastguard Worker break;
153*6777b538SAndroid Build Coastguard Worker case VT_UNKNOWN:
154*6777b538SAndroid Build Coastguard Worker scoped_variant.Set(CreateAndPopulateSafearray<VT_UNKNOWN>());
155*6777b538SAndroid Build Coastguard Worker break;
156*6777b538SAndroid Build Coastguard Worker // The default case shouldn't be reachable, but if we added support for more
157*6777b538SAndroid Build Coastguard Worker // VARTYPEs to base::win::internal::VariantConverter<> and they were
158*6777b538SAndroid Build Coastguard Worker // inserted into a VariantVector then it would be possible to reach the
159*6777b538SAndroid Build Coastguard Worker // default case for those new types until implemented.
160*6777b538SAndroid Build Coastguard Worker //
161*6777b538SAndroid Build Coastguard Worker // Because the switch is against VARTYPE (unsigned short) and not VARENUM,
162*6777b538SAndroid Build Coastguard Worker // removing the default case will not result in build warnings/errors if
163*6777b538SAndroid Build Coastguard Worker // there are missing cases. It is important that this uses VARTYPE rather
164*6777b538SAndroid Build Coastguard Worker // than VARENUM, because in the future we may want to support complex
165*6777b538SAndroid Build Coastguard Worker // VARTYPES. For example a value within VT_TYPEMASK that's joined something
166*6777b538SAndroid Build Coastguard Worker // outside the typemask like VT_ARRAY or VT_BYREF.
167*6777b538SAndroid Build Coastguard Worker default:
168*6777b538SAndroid Build Coastguard Worker NOTREACHED();
169*6777b538SAndroid Build Coastguard Worker break;
170*6777b538SAndroid Build Coastguard Worker }
171*6777b538SAndroid Build Coastguard Worker
172*6777b538SAndroid Build Coastguard Worker // CreateAndPopulateSafearray handles resetting |this| to VT_EMPTY because it
173*6777b538SAndroid Build Coastguard Worker // transfers ownership of each element to the SAFEARRAY.
174*6777b538SAndroid Build Coastguard Worker return scoped_variant.Release();
175*6777b538SAndroid Build Coastguard Worker }
176*6777b538SAndroid Build Coastguard Worker
Compare(const VARIANT & other,bool ignore_case) const177*6777b538SAndroid Build Coastguard Worker int VariantVector::Compare(const VARIANT& other, bool ignore_case) const {
178*6777b538SAndroid Build Coastguard Worker // If the element variant types are different, compare against the types.
179*6777b538SAndroid Build Coastguard Worker if (Type() != (V_VT(&other) & VT_TYPEMASK))
180*6777b538SAndroid Build Coastguard Worker return (Type() < (V_VT(&other) & VT_TYPEMASK)) ? (-1) : 1;
181*6777b538SAndroid Build Coastguard Worker
182*6777b538SAndroid Build Coastguard Worker // Both have an empty variant type so they are the same.
183*6777b538SAndroid Build Coastguard Worker if (Type() == VT_EMPTY)
184*6777b538SAndroid Build Coastguard Worker return 0;
185*6777b538SAndroid Build Coastguard Worker
186*6777b538SAndroid Build Coastguard Worker int compare_result = 0;
187*6777b538SAndroid Build Coastguard Worker if (V_ISARRAY(&other)) {
188*6777b538SAndroid Build Coastguard Worker compare_result = Compare(V_ARRAY(&other), ignore_case);
189*6777b538SAndroid Build Coastguard Worker } else {
190*6777b538SAndroid Build Coastguard Worker compare_result = vector_[0].Compare(other, ignore_case);
191*6777b538SAndroid Build Coastguard Worker // If the first element is equal to |other|, and |vector_|
192*6777b538SAndroid Build Coastguard Worker // has more than one element, then |vector_| is greater.
193*6777b538SAndroid Build Coastguard Worker if (!compare_result && Size() > 1)
194*6777b538SAndroid Build Coastguard Worker compare_result = 1;
195*6777b538SAndroid Build Coastguard Worker }
196*6777b538SAndroid Build Coastguard Worker return compare_result;
197*6777b538SAndroid Build Coastguard Worker }
198*6777b538SAndroid Build Coastguard Worker
Compare(const VariantVector & other,bool ignore_case) const199*6777b538SAndroid Build Coastguard Worker int VariantVector::Compare(const VariantVector& other, bool ignore_case) const {
200*6777b538SAndroid Build Coastguard Worker // If the element variant types are different, compare against the types.
201*6777b538SAndroid Build Coastguard Worker if (Type() != other.Type())
202*6777b538SAndroid Build Coastguard Worker return (Type() < other.Type()) ? (-1) : 1;
203*6777b538SAndroid Build Coastguard Worker
204*6777b538SAndroid Build Coastguard Worker // Both have an empty variant type so they are the same.
205*6777b538SAndroid Build Coastguard Worker if (Type() == VT_EMPTY)
206*6777b538SAndroid Build Coastguard Worker return 0;
207*6777b538SAndroid Build Coastguard Worker
208*6777b538SAndroid Build Coastguard Worker auto iter1 = vector_.begin();
209*6777b538SAndroid Build Coastguard Worker auto iter2 = other.vector_.begin();
210*6777b538SAndroid Build Coastguard Worker for (; (iter1 != vector_.end()) && (iter2 != other.vector_.end());
211*6777b538SAndroid Build Coastguard Worker ++iter1, ++iter2) {
212*6777b538SAndroid Build Coastguard Worker int compare_result = iter1->Compare(*iter2, ignore_case);
213*6777b538SAndroid Build Coastguard Worker if (compare_result)
214*6777b538SAndroid Build Coastguard Worker return compare_result;
215*6777b538SAndroid Build Coastguard Worker }
216*6777b538SAndroid Build Coastguard Worker // There are more elements in |this|, so |this| is greater than |other|.
217*6777b538SAndroid Build Coastguard Worker if (iter1 != vector_.end())
218*6777b538SAndroid Build Coastguard Worker return 1;
219*6777b538SAndroid Build Coastguard Worker // There are more elements in |other|, so |this| is less than |other|.
220*6777b538SAndroid Build Coastguard Worker if (iter2 != other.vector_.end())
221*6777b538SAndroid Build Coastguard Worker return -1;
222*6777b538SAndroid Build Coastguard Worker return 0;
223*6777b538SAndroid Build Coastguard Worker }
224*6777b538SAndroid Build Coastguard Worker
Compare(SAFEARRAY * safearray,bool ignore_case) const225*6777b538SAndroid Build Coastguard Worker int VariantVector::Compare(SAFEARRAY* safearray, bool ignore_case) const {
226*6777b538SAndroid Build Coastguard Worker VARTYPE safearray_vartype;
227*6777b538SAndroid Build Coastguard Worker // If we fail to get the element variant type for the SAFEARRAY, then
228*6777b538SAndroid Build Coastguard Worker // arbitrarily treat |this| as greater.
229*6777b538SAndroid Build Coastguard Worker if (FAILED(SafeArrayGetVartype(safearray, &safearray_vartype)))
230*6777b538SAndroid Build Coastguard Worker return 1;
231*6777b538SAndroid Build Coastguard Worker
232*6777b538SAndroid Build Coastguard Worker // If the element variant types are different, compare against the types.
233*6777b538SAndroid Build Coastguard Worker if (Type() != safearray_vartype)
234*6777b538SAndroid Build Coastguard Worker return (Type() < safearray_vartype) ? (-1) : 1;
235*6777b538SAndroid Build Coastguard Worker
236*6777b538SAndroid Build Coastguard Worker ScopedSafearray scoped_safearray(safearray);
237*6777b538SAndroid Build Coastguard Worker int compare_result = 0;
238*6777b538SAndroid Build Coastguard Worker switch (Type()) {
239*6777b538SAndroid Build Coastguard Worker case VT_BOOL:
240*6777b538SAndroid Build Coastguard Worker compare_result = CompareAgainstSafearray<VT_BOOL>(
241*6777b538SAndroid Build Coastguard Worker vector_, scoped_safearray, ignore_case);
242*6777b538SAndroid Build Coastguard Worker break;
243*6777b538SAndroid Build Coastguard Worker case VT_I1:
244*6777b538SAndroid Build Coastguard Worker compare_result = CompareAgainstSafearray<VT_I1>(vector_, scoped_safearray,
245*6777b538SAndroid Build Coastguard Worker ignore_case);
246*6777b538SAndroid Build Coastguard Worker break;
247*6777b538SAndroid Build Coastguard Worker case VT_UI1:
248*6777b538SAndroid Build Coastguard Worker compare_result = CompareAgainstSafearray<VT_UI1>(
249*6777b538SAndroid Build Coastguard Worker vector_, scoped_safearray, ignore_case);
250*6777b538SAndroid Build Coastguard Worker break;
251*6777b538SAndroid Build Coastguard Worker case VT_I2:
252*6777b538SAndroid Build Coastguard Worker compare_result = CompareAgainstSafearray<VT_I2>(vector_, scoped_safearray,
253*6777b538SAndroid Build Coastguard Worker ignore_case);
254*6777b538SAndroid Build Coastguard Worker break;
255*6777b538SAndroid Build Coastguard Worker case VT_UI2:
256*6777b538SAndroid Build Coastguard Worker compare_result = CompareAgainstSafearray<VT_UI2>(
257*6777b538SAndroid Build Coastguard Worker vector_, scoped_safearray, ignore_case);
258*6777b538SAndroid Build Coastguard Worker break;
259*6777b538SAndroid Build Coastguard Worker case VT_I4:
260*6777b538SAndroid Build Coastguard Worker compare_result = CompareAgainstSafearray<VT_I4>(vector_, scoped_safearray,
261*6777b538SAndroid Build Coastguard Worker ignore_case);
262*6777b538SAndroid Build Coastguard Worker break;
263*6777b538SAndroid Build Coastguard Worker case VT_UI4:
264*6777b538SAndroid Build Coastguard Worker compare_result = CompareAgainstSafearray<VT_UI4>(
265*6777b538SAndroid Build Coastguard Worker vector_, scoped_safearray, ignore_case);
266*6777b538SAndroid Build Coastguard Worker break;
267*6777b538SAndroid Build Coastguard Worker case VT_I8:
268*6777b538SAndroid Build Coastguard Worker compare_result = CompareAgainstSafearray<VT_I8>(vector_, scoped_safearray,
269*6777b538SAndroid Build Coastguard Worker ignore_case);
270*6777b538SAndroid Build Coastguard Worker break;
271*6777b538SAndroid Build Coastguard Worker case VT_UI8:
272*6777b538SAndroid Build Coastguard Worker compare_result = CompareAgainstSafearray<VT_UI8>(
273*6777b538SAndroid Build Coastguard Worker vector_, scoped_safearray, ignore_case);
274*6777b538SAndroid Build Coastguard Worker break;
275*6777b538SAndroid Build Coastguard Worker case VT_R4:
276*6777b538SAndroid Build Coastguard Worker compare_result = CompareAgainstSafearray<VT_R4>(vector_, scoped_safearray,
277*6777b538SAndroid Build Coastguard Worker ignore_case);
278*6777b538SAndroid Build Coastguard Worker break;
279*6777b538SAndroid Build Coastguard Worker case VT_R8:
280*6777b538SAndroid Build Coastguard Worker compare_result = CompareAgainstSafearray<VT_R8>(vector_, scoped_safearray,
281*6777b538SAndroid Build Coastguard Worker ignore_case);
282*6777b538SAndroid Build Coastguard Worker break;
283*6777b538SAndroid Build Coastguard Worker case VT_DATE:
284*6777b538SAndroid Build Coastguard Worker compare_result = CompareAgainstSafearray<VT_DATE>(
285*6777b538SAndroid Build Coastguard Worker vector_, scoped_safearray, ignore_case);
286*6777b538SAndroid Build Coastguard Worker break;
287*6777b538SAndroid Build Coastguard Worker case VT_BSTR:
288*6777b538SAndroid Build Coastguard Worker compare_result = CompareAgainstSafearray<VT_BSTR>(
289*6777b538SAndroid Build Coastguard Worker vector_, scoped_safearray, ignore_case);
290*6777b538SAndroid Build Coastguard Worker break;
291*6777b538SAndroid Build Coastguard Worker case VT_DISPATCH:
292*6777b538SAndroid Build Coastguard Worker compare_result = CompareAgainstSafearray<VT_DISPATCH>(
293*6777b538SAndroid Build Coastguard Worker vector_, scoped_safearray, ignore_case);
294*6777b538SAndroid Build Coastguard Worker break;
295*6777b538SAndroid Build Coastguard Worker case VT_UNKNOWN:
296*6777b538SAndroid Build Coastguard Worker compare_result = CompareAgainstSafearray<VT_UNKNOWN>(
297*6777b538SAndroid Build Coastguard Worker vector_, scoped_safearray, ignore_case);
298*6777b538SAndroid Build Coastguard Worker break;
299*6777b538SAndroid Build Coastguard Worker // The default case shouldn't be reachable, but if we added support for more
300*6777b538SAndroid Build Coastguard Worker // VARTYPEs to base::win::internal::VariantConverter<> and they were
301*6777b538SAndroid Build Coastguard Worker // inserted into a VariantVector then it would be possible to reach the
302*6777b538SAndroid Build Coastguard Worker // default case for those new types until implemented.
303*6777b538SAndroid Build Coastguard Worker //
304*6777b538SAndroid Build Coastguard Worker // Because the switch is against VARTYPE (unsigned short) and not VARENUM,
305*6777b538SAndroid Build Coastguard Worker // removing the default case will not result in build warnings/errors if
306*6777b538SAndroid Build Coastguard Worker // there are missing cases. It is important that this uses VARTYPE rather
307*6777b538SAndroid Build Coastguard Worker // than VARENUM, because in the future we may want to support complex
308*6777b538SAndroid Build Coastguard Worker // VARTYPES. For example a value within VT_TYPEMASK that's joined something
309*6777b538SAndroid Build Coastguard Worker // outside the typemask like VT_ARRAY or VT_BYREF.
310*6777b538SAndroid Build Coastguard Worker default:
311*6777b538SAndroid Build Coastguard Worker NOTREACHED();
312*6777b538SAndroid Build Coastguard Worker compare_result = 1;
313*6777b538SAndroid Build Coastguard Worker break;
314*6777b538SAndroid Build Coastguard Worker }
315*6777b538SAndroid Build Coastguard Worker
316*6777b538SAndroid Build Coastguard Worker scoped_safearray.Release();
317*6777b538SAndroid Build Coastguard Worker return compare_result;
318*6777b538SAndroid Build Coastguard Worker }
319*6777b538SAndroid Build Coastguard Worker
320*6777b538SAndroid Build Coastguard Worker template <VARTYPE ElementVartype>
CreateAndPopulateSafearray()321*6777b538SAndroid Build Coastguard Worker SAFEARRAY* VariantVector::CreateAndPopulateSafearray() {
322*6777b538SAndroid Build Coastguard Worker DCHECK(!Empty());
323*6777b538SAndroid Build Coastguard Worker
324*6777b538SAndroid Build Coastguard Worker ScopedSafearray scoped_safearray(
325*6777b538SAndroid Build Coastguard Worker SafeArrayCreateVector(ElementVartype, 0, checked_cast<ULONG>(Size())));
326*6777b538SAndroid Build Coastguard Worker if (!scoped_safearray.Get()) {
327*6777b538SAndroid Build Coastguard Worker constexpr size_t kElementSize =
328*6777b538SAndroid Build Coastguard Worker sizeof(typename internal::VariantConverter<ElementVartype>::Type);
329*6777b538SAndroid Build Coastguard Worker base::TerminateBecauseOutOfMemory(sizeof(SAFEARRAY) +
330*6777b538SAndroid Build Coastguard Worker (Size() * kElementSize));
331*6777b538SAndroid Build Coastguard Worker }
332*6777b538SAndroid Build Coastguard Worker
333*6777b538SAndroid Build Coastguard Worker std::optional<ScopedSafearray::LockScope<ElementVartype>> lock_scope =
334*6777b538SAndroid Build Coastguard Worker scoped_safearray.CreateLockScope<ElementVartype>();
335*6777b538SAndroid Build Coastguard Worker DCHECK(lock_scope);
336*6777b538SAndroid Build Coastguard Worker
337*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < Size(); ++i) {
338*6777b538SAndroid Build Coastguard Worker VARIANT element = vector_[i].Release();
339*6777b538SAndroid Build Coastguard Worker (*lock_scope)[i] =
340*6777b538SAndroid Build Coastguard Worker internal::VariantConverter<ElementVartype>::RawGet(element);
341*6777b538SAndroid Build Coastguard Worker }
342*6777b538SAndroid Build Coastguard Worker Reset();
343*6777b538SAndroid Build Coastguard Worker
344*6777b538SAndroid Build Coastguard Worker return scoped_safearray.Release();
345*6777b538SAndroid Build Coastguard Worker }
346*6777b538SAndroid Build Coastguard Worker
347*6777b538SAndroid Build Coastguard Worker } // namespace win
348*6777b538SAndroid Build Coastguard Worker } // namespace base
349