summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authortommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-25 22:35:45 +0000
committertommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-25 22:35:45 +0000
commit6e1f48fb52edc5583db8c6deea2f00600bdddb8b (patch)
tree01689bb373f9383c66755b47f1c8b0b846537078 /base
parent003849a2a44f7e8c7ae7a081d7c6bc0c0f9b5a2d (diff)
downloadchromium_src-6e1f48fb52edc5583db8c6deea2f00600bdddb8b.zip
chromium_src-6e1f48fb52edc5583db8c6deea2f00600bdddb8b.tar.gz
chromium_src-6e1f48fb52edc5583db8c6deea2f00600bdddb8b.tar.bz2
Adding a Set() method for copying (not taking ownership) a variant over to the ScopedVariant and a couple of new constructors for IDispatch and IUnknown. includes tests.
Review URL: http://codereview.chromium.org/42569 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12506 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r--base/scoped_variant_win.cc31
-rw-r--r--base/scoped_variant_win.h18
-rw-r--r--base/scoped_variant_win_unittest.cc42
3 files changed, 91 insertions, 0 deletions
diff --git a/base/scoped_variant_win.cc b/base/scoped_variant_win.cc
index 5653520..6593a477 100644
--- a/base/scoped_variant_win.cc
+++ b/base/scoped_variant_win.cc
@@ -28,6 +28,21 @@ ScopedVariant::ScopedVariant(int value, VARTYPE vt) {
var_.lVal = value;
}
+ScopedVariant::ScopedVariant(IDispatch* dispatch) {
+ var_.vt = VT_EMPTY;
+ Set(dispatch);
+}
+
+ScopedVariant::ScopedVariant(IUnknown* unknown) {
+ var_.vt = VT_EMPTY;
+ Set(unknown);
+}
+
+ScopedVariant::ScopedVariant(const VARIANT& var) {
+ var_.vt = VT_EMPTY;
+ Set(var);
+}
+
void ScopedVariant::Reset(const VARIANT& var) {
if (&var != &var_) {
::VariantClear(&var_);
@@ -187,6 +202,22 @@ void ScopedVariant::Set(SAFEARRAY* array) {
}
}
+void ScopedVariant::Set(const VARIANT& var) {
+ DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
+ if (FAILED(::VariantCopy(&var_, &var))) {
+ DLOG(ERROR) << "VariantCopy failed";
+ var_.vt = VT_EMPTY;
+ }
+}
+
+ScopedVariant& ScopedVariant::operator=(const VARIANT& var) {
+ if (&var != &var_) {
+ VariantClear(&var_);
+ Set(var);
+ }
+ return *this;
+}
+
bool ScopedVariant::IsLeakableVarType(VARTYPE vt) {
bool leakable = false;
switch (vt & VT_TYPEMASK) {
diff --git a/base/scoped_variant_win.h b/base/scoped_variant_win.h
index 50c9ce3..909e4da 100644
--- a/base/scoped_variant_win.h
+++ b/base/scoped_variant_win.h
@@ -40,6 +40,15 @@ class ScopedVariant {
// VARIANT.lVal (32 bit sized field).
explicit ScopedVariant(int value, VARTYPE vt = VT_I4);
+ // VT_DISPATCH
+ explicit ScopedVariant(IDispatch* dispatch);
+
+ // VT_UNKNOWN
+ explicit ScopedVariant(IUnknown* unknown);
+
+ // Copies the variant.
+ explicit ScopedVariant(const VARIANT& var);
+
~ScopedVariant();
inline VARTYPE type() const {
@@ -83,6 +92,11 @@ class ScopedVariant {
void Set(double r64);
void Set(bool b);
+ // Creates a copy of |var| and assigns as this instance's value.
+ // Note that this is different from the Reset() method that's used to
+ // free the current value and assume ownership.
+ void Set(const VARIANT& var);
+
// COM object setters
void Set(IDispatch* disp);
void Set(IUnknown* unk);
@@ -102,6 +116,10 @@ class ScopedVariant {
return &var_;
}
+ // Like other scoped classes (e.g scoped_refptr, ScopedComPtr, ScopedBstr)
+ // we support the assignment operator for the type we wrap.
+ ScopedVariant& operator=(const VARIANT& var);
+
// A hack to pass a pointer to the variant where the accepting
// function treats the variant as an input-only, read-only value
// but the function prototype requires a non const variant pointer.
diff --git a/base/scoped_variant_win_unittest.cc b/base/scoped_variant_win_unittest.cc
index e826edd..8588e17 100644
--- a/base/scoped_variant_win_unittest.cc
+++ b/base/scoped_variant_win_unittest.cc
@@ -198,6 +198,48 @@ TEST(ScopedVariantTest, ScopedVariant) {
var.Reset();
EXPECT_EQ(0, faker.ref_count());
+ {
+ ScopedVariant disp_var(&faker);
+ EXPECT_EQ(VT_DISPATCH, disp_var.type());
+ EXPECT_EQ(&faker, V_DISPATCH(&disp_var));
+ EXPECT_EQ(1, faker.ref_count());
+ }
+ EXPECT_EQ(0, faker.ref_count());
+
+ {
+ ScopedVariant ref1(&faker);
+ EXPECT_EQ(1, faker.ref_count());
+ ScopedVariant ref2(static_cast<const VARIANT&>(ref1));
+ EXPECT_EQ(2, faker.ref_count());
+ ScopedVariant ref3;
+ ref3 = static_cast<const VARIANT&>(ref2);
+ EXPECT_EQ(3, faker.ref_count());
+ }
+ EXPECT_EQ(0, faker.ref_count());
+
+ {
+ ScopedVariant unk_var(static_cast<IUnknown*>(&faker));
+ EXPECT_EQ(VT_UNKNOWN, unk_var.type());
+ EXPECT_EQ(&faker, V_UNKNOWN(&unk_var));
+ EXPECT_EQ(1, faker.ref_count());
+ }
+ EXPECT_EQ(0, faker.ref_count());
+
+ VARIANT raw;
+ raw.vt = VT_UNKNOWN;
+ raw.punkVal = &faker;
+ EXPECT_EQ(0, faker.ref_count());
+ var.Set(raw);
+ EXPECT_EQ(1, faker.ref_count());
+ var.Reset();
+ EXPECT_EQ(0, faker.ref_count());
+
+ {
+ ScopedVariant number(123);
+ EXPECT_EQ(VT_I4, number.type());
+ EXPECT_EQ(123, V_I4(&number));
+ }
+
// SAFEARRAY tests
var.Set(static_cast<SAFEARRAY*>(NULL));
EXPECT_EQ(VT_EMPTY, var.type());