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 144 145
|
// 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::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();
// 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>
requires(ExpectedVartype != VT_BOOL)
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>
requires(ExpectedVartype == VT_BOOL)
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_;
};
inline bool operator==(const VariantVector& lhs, const VariantVector& rhs) {
return !lhs.Compare(rhs);
}
} // namespace base::win
#endif // BASE_WIN_VARIANT_VECTOR_H_
|