xref: /aosp_15_r20/external/cronet/base/win/scoped_variant.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2011 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_SCOPED_VARIANT_H_
6 #define BASE_WIN_SCOPED_VARIANT_H_
7 
8 #include <windows.h>
9 
10 #include <oleauto.h>
11 #include <stdint.h>
12 
13 #include "base/base_export.h"
14 
15 namespace base {
16 namespace win {
17 
18 // Scoped VARIANT class for automatically freeing a COM VARIANT at the
19 // end of a scope.  Additionally provides a few functions to make the
20 // encapsulated VARIANT easier to use.
21 // Instead of inheriting from VARIANT, we take the containment approach
22 // in order to have more control over the usage of the variant and guard
23 // against memory leaks.
24 class BASE_EXPORT ScopedVariant {
25  public:
26   // Declaration of a global variant variable that's always VT_EMPTY
27   static const VARIANT kEmptyVariant;
28 
29   // Default constructor.
ScopedVariant()30   ScopedVariant() {
31     // This is equivalent to what VariantInit does, but less code.
32     var_.vt = VT_EMPTY;
33   }
34 
35   // Constructor to create a new VT_BSTR VARIANT.
36   // NOTE: Do not pass a BSTR to this constructor expecting ownership to
37   // be transferred
38   explicit ScopedVariant(const wchar_t* str);
39 
40   // Creates a new VT_BSTR variant of a specified length.
41   ScopedVariant(const wchar_t* str, UINT length);
42 
43   // Creates a new integral type variant and assigns the value to
44   // VARIANT.lVal (32 bit sized field).
45   explicit ScopedVariant(long value,  // NOLINT(runtime/int)
46                          VARTYPE vt = VT_I4);
47 
48   // Creates a new integral type variant for the int type and assigns the value
49   // to VARIANT.lVal (32 bit sized field).
50   explicit ScopedVariant(int value);
51 
52   // Creates a new boolean (VT_BOOL) variant and assigns the value to
53   // VARIANT.boolVal.
54   explicit ScopedVariant(bool value);
55 
56   // Creates a new double-precision type variant.  |vt| must be either VT_R8
57   // or VT_DATE.
58   explicit ScopedVariant(double value, VARTYPE vt = VT_R8);
59 
60   // VT_DISPATCH
61   explicit ScopedVariant(IDispatch* dispatch);
62 
63   // VT_UNKNOWN
64   explicit ScopedVariant(IUnknown* unknown);
65 
66   // SAFEARRAY
67   explicit ScopedVariant(SAFEARRAY* safearray);
68 
69   // Copies the variant.
70   explicit ScopedVariant(const VARIANT& var);
71 
72   // Moves the wrapped variant into another ScopedVariant.
73   ScopedVariant(ScopedVariant&& var);
74 
75   ScopedVariant(const ScopedVariant&) = delete;
76   ScopedVariant& operator=(const ScopedVariant&) = delete;
77 
78   ~ScopedVariant();
79 
type()80   inline VARTYPE type() const { return var_.vt; }
81 
82   // Give ScopedVariant ownership over an already allocated VARIANT.
83   void Reset(const VARIANT& var = kEmptyVariant);
84 
85   // Releases ownership of the VARIANT to the caller.
86   VARIANT Release();
87 
88   // Swap two ScopedVariant's.
89   void Swap(ScopedVariant& var);
90 
91   // Returns a copy of the variant.
92   VARIANT Copy() const;
93 
94   // The return value is 0 if the variants are equal, 1 if this object is
95   // greater than |other|, -1 if it is smaller.
96   // Comparison with an array VARIANT is not supported.
97   // 1. VT_NULL and VT_EMPTY is always considered less-than any other VARTYPE.
98   // 2. If both VARIANTS have either VT_UNKNOWN or VT_DISPATCH even if the
99   //    VARTYPEs do not match, the address of its IID_IUnknown is compared to
100   //    guarantee a logical ordering even though it is not a meaningful order.
101   //    e.g. (a.Compare(b) != b.Compare(a)) unless (a == b).
102   // 3. If the VARTYPEs do not match, then the value of the VARTYPE is compared.
103   // 4. Comparing VT_BSTR values is a lexicographical comparison of the contents
104   //    of the BSTR, taking into account |ignore_case|.
105   // 5. Otherwise returns the lexicographical comparison of the values held by
106   //    the two VARIANTS that share the same VARTYPE.
107   int Compare(const VARIANT& other, bool ignore_case = false) const;
108 
109   // Retrieves the pointer address.
110   // Used to receive a VARIANT as an out argument (and take ownership).
111   // The function DCHECKs on the current value being empty/null.
112   // Usage: GetVariant(var.receive());
113   VARIANT* Receive();
114 
115   void Set(const wchar_t* str);
116 
117   // Setters for simple types.
118   void Set(int8_t i8);
119   void Set(uint8_t ui8);
120   void Set(int16_t i16);
121   void Set(uint16_t ui16);
122   void Set(int32_t i32);
123   void Set(uint32_t ui32);
124   void Set(int64_t i64);
125   void Set(uint64_t ui64);
126   void Set(float r32);
127   void Set(double r64);
128   void Set(bool b);
129 
130   // Creates a copy of |var| and assigns as this instance's value.
131   // Note that this is different from the Reset() method that's used to
132   // free the current value and assume ownership.
133   void Set(const VARIANT& var);
134 
135   // COM object setters
136   void Set(IDispatch* disp);
137   void Set(IUnknown* unk);
138 
139   // SAFEARRAY support
140   void Set(SAFEARRAY* array);
141 
142   // Special setter for DATE since DATE is a double and we already have
143   // a setter for double.
144   void SetDate(DATE date);
145 
146   // Allows const access to the contained variant without DCHECKs etc.
147   // This support is necessary for the V_XYZ (e.g. V_BSTR) set of macros to
148   // work properly but still doesn't allow modifications since we want control
149   // over that.
ptr()150   const VARIANT* ptr() const { return &var_; }
151 
152   // Moves the ScopedVariant to another instance.
153   ScopedVariant& operator=(ScopedVariant&& var);
154 
155   // Like other scoped classes (e.g. scoped_refptr, ScopedBstr,
156   // Microsoft::WRL::ComPtr) we support the assignment operator for the type we
157   // wrap.
158   ScopedVariant& operator=(const VARIANT& var);
159 
160   // A hack to pass a pointer to the variant where the accepting
161   // function treats the variant as an input-only, read-only value
162   // but the function prototype requires a non const variant pointer.
163   // There's no DCHECK or anything here.  Callers must know what they're doing.
AsInput()164   VARIANT* AsInput() const {
165     // The nature of this function is const, so we declare
166     // it as such and cast away the constness here.
167     return const_cast<VARIANT*>(&var_);
168   }
169 
170   // Allows the ScopedVariant instance to be passed to functions either by value
171   // or by const reference.
172   operator const VARIANT&() const { return var_; }
173 
174   // Used as a debug check to see if we're leaking anything.
175   static bool IsLeakableVarType(VARTYPE vt);
176 
177  protected:
178   VARIANT var_;
179 
180  private:
181   // Comparison operators for ScopedVariant are not supported at this point.
182   // Use the Compare method instead.
183   bool operator==(const ScopedVariant& var) const;
184   bool operator!=(const ScopedVariant& var) const;
185 };
186 
187 }  // namespace win
188 }  // namespace base
189 
190 #endif  // BASE_WIN_SCOPED_VARIANT_H_
191