1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
base / win / variant_vector.h [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_WIN_VARIANT_VECTOR_H_
#define BASE_WIN_VARIANT_VECTOR_H_
#include <objbase.h>
#include <oleauto.h>
#include <type_traits>
#include <utility>
#include <vector>
#include "base/base_export.h"
#include "base/check.h"
#include "base/logging.h"
#include "base/win/scoped_variant.h"
#include "base/win/variant_conversions.h"
namespace base {
namespace win {
// This class has RAII semantics and is used to build a vector for a specific
// OLE VARTYPE, and handles converting the data to a VARIANT or VARIANT
// SAFEARRAY. It can be populated similarly to a STL vector<T>, but without the
// compile-time requirement of knowing what element type the VariantVector will
// store. The VariantVector only allows one variant type to be stored at a time.
//
// This class can release ownership of its contents to a VARIANT, and will
// automatically allocate + populate a SAFEARRAY as needed or when explicitly
// requesting that the results be released as a SAFEARRAY.
class BASE_EXPORT VariantVector final {
public:
VariantVector();
VariantVector(VariantVector&& other);
VariantVector& operator=(VariantVector&& other);
VariantVector(const VariantVector&) = delete;
VariantVector& operator=(const VariantVector&) = delete;
~VariantVector();
bool operator==(const VariantVector& other) const;
bool operator!=(const VariantVector& other) const;
// Returns the variant type for data stored in the VariantVector.
VARTYPE Type() const { return vartype_; }
// Returns the number of elements in the VariantVector.
size_t Size() const { return vector_.size(); }
// Returns whether or not there are any elements.
bool Empty() const { return vector_.empty(); }
// Resets VariantVector to its default state, releasing any managed content.
void Reset();
// Helper template method for selecting the correct |Insert| call based
// on the underlying type that is expected for a VARTYPE.
template <VARTYPE ExpectedVartype,
std::enable_if_t<ExpectedVartype != VT_BOOL, int> = 0>
void Insert(
typename internal::VariantConverter<ExpectedVartype>::Type value) {
if (vartype_ == VT_EMPTY)
vartype_ = ExpectedVartype;
AssertVartype<ExpectedVartype>();
ScopedVariant scoped_variant;
scoped_variant.Set(value);
vector_.push_back(std::move(scoped_variant));
}
// Specialize VT_BOOL to accept a bool type instead of VARIANT_BOOL,
// this is to make calling insert with VT_BOOL safer.
template <VARTYPE ExpectedVartype,
std::enable_if_t<ExpectedVartype == VT_BOOL, int> = 0>
void Insert(bool value) {
if (vartype_ == VT_EMPTY)
vartype_ = ExpectedVartype;
AssertVartype<ExpectedVartype>();
ScopedVariant scoped_variant;
scoped_variant.Set(value);
vector_.push_back(std::move(scoped_variant));
}
// Specialize VT_DATE because ScopedVariant has a separate SetDate method,
// this is because VT_R8 and VT_DATE share the same underlying type.
template <>
void Insert<VT_DATE>(
typename internal::VariantConverter<VT_DATE>::Type value) {
if (vartype_ == VT_EMPTY)
vartype_ = VT_DATE;
AssertVartype<VT_DATE>();
ScopedVariant scoped_variant;
scoped_variant.SetDate(value);
vector_.push_back(std::move(scoped_variant));
}
// Populates a VARIANT based on what is stored, transferring ownership
// of managed contents.
// This is only valid when the VariantVector is empty or has a single element.
// The VariantVector is then reset.
VARIANT ReleaseAsScalarVariant();
// Populates a VARIANT as a SAFEARRAY, even if there is only one element.
// The VariantVector is then reset.
VARIANT ReleaseAsSafearrayVariant();
// Lexicographical comparison between a VariantVector and a VARIANT.
// The return value is 0 if the variants are equal, 1 if this object is
// greater than |other|, -1 if it is smaller.
int Compare(const VARIANT& other, bool ignore_case = false) const;
// Lexicographical comparison between a VariantVector and a SAFEARRAY.
int Compare(SAFEARRAY* safearray, bool ignore_case = false) const;
// Lexicographical comparison between two VariantVectors.
int Compare(const VariantVector& other, bool ignore_case = false) const;
private:
// Returns true if the current |vartype_| is compatible with |ExpectedVartype|
// for inserting into |vector_|.
template <VARTYPE ExpectedVartype>
void AssertVartype() const {
DCHECK(
internal::VariantConverter<ExpectedVartype>::IsConvertibleTo(vartype_))
<< "Type mismatch, " << ExpectedVartype << " is not convertible to "
<< Type();
}
// Creates a SAFEARRAY and populates it with teh values held by each VARIANT
// in |vector_|, transferring ownership to the new SAFEARRAY.
// The VariantVector is reset when successful.
template <VARTYPE ElementVartype>
SAFEARRAY* CreateAndPopulateSafearray();
VARTYPE vartype_ = VT_EMPTY;
std::vector<ScopedVariant> vector_;
};
} // namespace win
} // namespace base
#endif // BASE_WIN_VARIANT_VECTOR_H_