summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYannick Guesnet <yannick.guesnet@univ-rouen.fr>2011-03-14 20:49:52 +0100
committerMurray Cumming <murrayc@murrayc.com>2011-03-16 10:30:38 +0100
commit4af5c32ac1c325a63d89e5a35ca8647c4a4bb908 (patch)
tree4e1b34e823936b4fff7c26e88cb798727ca0041c
parent584a67f8194fce32933ef1cef464a251f56095b9 (diff)
downloadglibmm-4af5c32ac1c325a63d89e5a35ca8647c4a4bb908.tar.gz
Variant: Add a cast operator.
* gio/src/glib/src/variant.[ccg|hg]: Add a VariantBase::cast_dynamic() static method. * tests/glibmm_variant/main.cc: Add some tests. This is useful because VariantBase can and will be passed by value sometimes and DBus may have actual Variant types whose underlying type will not be known at compile time (this note was by Murray). Bug #644146
-rw-r--r--ChangeLog14
-rw-r--r--glib/src/variant.ccg19
-rw-r--r--glib/src/variant.hg29
-rw-r--r--tests/glibmm_variant/main.cc49
4 files changed, 110 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index b48ea39c..3467618c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2011-03-14 Yannick Guesnet <Yannick.Guesnet@univ-rouen.fr>
+
+ Variant: Add a cast operator.
+
+ * gio/src/glib/src/variant.[ccg|hg]: Add a VariantBase::cast_dynamic()
+ static method.
+ * tests/glibmm_variant/main.cc: Add some tests.
+
+ This is useful because VariantBase can and will be passed by value sometimes
+ and DBus may have actual Variant types whose underlying type will not be
+ known at compile time (this note was by Murray).
+
+ Bug #644146
+
2011-03-16 Murray Cumming <murrayc@murrayc.com>
Fix missing doc-install.pl problem with the tarball build.
diff --git a/glib/src/variant.ccg b/glib/src/variant.ccg
index 6246304c..c8dc2420 100644
--- a/glib/src/variant.ccg
+++ b/glib/src/variant.ccg
@@ -90,6 +90,25 @@ void VariantContainerBase::get(VariantBase& child, gsize index) const
child.init(gvariant);
}
+// VariantContainerBase has no method variant_type()
+template<>
+VariantContainerBase VariantBase::cast_dynamic<VariantContainerBase>(const VariantBase& v)
+throw(std::bad_cast)
+{
+ if(v.gobj() == NULL)
+ {
+ return VariantContainerBase();
+ }
+ if(v.get_type().is_container())
+ {
+ return VariantContainerBase(const_cast<GVariant*>(v.gobj()), true);
+ }
+ else
+ {
+ throw std::bad_cast();
+ }
+}
+
bool VariantContainerBase::get_maybe(Glib::VariantBase& maybe) const
{
GVariant* const g_value =
diff --git a/glib/src/variant.hg b/glib/src/variant.hg
index 71612787..d1e7d6cb 100644
--- a/glib/src/variant.hg
+++ b/glib/src/variant.hg
@@ -25,6 +25,7 @@ _DEFS(glibmm,glib)
#include <vector>
#include <map>
#include <stdexcept>
+#include <typeinfo>
namespace Glib
{
@@ -125,8 +126,31 @@ public:
*/
void byteswap(VariantBase& result) const;
_IGNORE(g_variant_byteswap)
+
+ template<class V_CastTo>
+ static V_CastTo cast_dynamic(const VariantBase& v)
+ throw(std::bad_cast);
+
};
+template<class V_CastTo>
+V_CastTo VariantBase::cast_dynamic(const VariantBase& v)
+throw(std::bad_cast)
+{
+ if(v.gobj() == NULL)
+ {
+ return V_CastTo();
+ }
+ if(v.is_of_type(V_CastTo::variant_type()))
+ {
+ return V_CastTo(const_cast<GVariant*>(v.gobj()), true);
+ }
+ else
+ {
+ throw std::bad_cast();
+ }
+}
+
/** Base class from which string variant classes derive.
* @newin{2,28}
* @ingroup Variant
@@ -256,6 +280,10 @@ public:
_IGNORE(g_variant_get_maybe)
};
+template<>
+VariantContainerBase VariantBase::cast_dynamic<VariantContainerBase>(const VariantBase& v)
+throw(std::bad_cast);
+
/** Template class used for the specialization of the Glib::Variant<> classes.
* @newin{2,28}
* @ingroup Variant
@@ -267,7 +295,6 @@ public:
typedef T CppType;
};
-
// Each specialization has (or should have) a variant_type() method that gets
// the type. So the C g_variant_get_type() function can be ignored.
_IGNORE(g_variant_get_type)
diff --git a/tests/glibmm_variant/main.cc b/tests/glibmm_variant/main.cc
index cfe12acb..1f463e43 100644
--- a/tests/glibmm_variant/main.cc
+++ b/tests/glibmm_variant/main.cc
@@ -8,6 +8,8 @@
std::stringstream debug;
std::ostream& ostr = debug;
+static void test_dynamic_cast();
+
int main(int, char**)
{
Glib::init();
@@ -107,5 +109,52 @@ int main(int, char**)
" in the variant are: " << value << '.' << std::endl;
}
+ test_dynamic_cast();
+
return EXIT_SUCCESS;
}
+
+static void test_dynamic_cast()
+{
+ Glib::Variant< int > v1 = Glib::Variant< int >::create(10);
+ Glib::VariantBase& v2 = v1;
+ Glib::Variant< int > v3 = Glib::VariantBase::cast_dynamic<Glib::Variant<int> >(v2);
+ g_assert(v3.get() == 10);
+
+ Glib::VariantBase v5 = v1;
+ v3 = Glib::VariantBase::cast_dynamic<Glib::Variant<int> >(v5);
+ g_assert(v3.get() == 10);
+
+ Glib::Variant< double > v4;
+ // v4 contain a NULL GVariant: The cast succeed
+ v3 = Glib::VariantBase::cast_dynamic<Glib::Variant<int> >(v4);
+
+ v4 = Glib::Variant< double >::create(1.0);
+ try
+ {
+ v3 = Glib::VariantBase::cast_dynamic<Glib::Variant<int> >(v4);
+ g_assert_not_reached();
+ }
+ catch(const std::bad_cast& e)
+ {
+ }
+
+ // A t-uple
+ std::vector<Glib::VariantBase> vec_var(2);
+ vec_var[0] = Glib::Variant<int>::create(1);
+ vec_var[1] = Glib::Variant<Glib::ustring>::create("coucou");
+ Glib::VariantContainerBase var_tuple = Glib::VariantContainerBase::create_tuple(vec_var);
+ g_assert(var_tuple.get_type_string() == "(is)");
+
+ v5 = var_tuple;
+ Glib::VariantContainerBase v6 = Glib::VariantBase::cast_dynamic<Glib::VariantContainerBase >(v5);
+
+ try
+ {
+ v6 = Glib::VariantBase::cast_dynamic<Glib::VariantContainerBase >(v1);
+ g_assert_not_reached();
+ }
+ catch (const std::bad_cast& e)
+ {
+ }
+}