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