xref: /aosp_15_r20/external/cronet/base/win/variant_vector.cc (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 #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