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