[glibmm] Variant: Allow containing complex types in arrays and in variants.
- From: Josà Alburquerque <jaalburqu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glibmm] Variant: Allow containing complex types in arrays and in variants.
- Date: Fri, 28 Dec 2012 16:31:31 +0000 (UTC)
commit 8460377403f9cb02f2fd3972a9dcfa1d978ab7ab
Author: Josà Alburquerque <jaalburqu svn gnome org>
Date: Fri Dec 28 11:10:46 2012 -0500
Variant: Allow containing complex types in arrays and in variants.
* glib/src/variant.hg (Variant< Variant<T> >): Add a new class capable
of containing any Variant<>. The class is just like
Variant<VariantBase> except that with it, it is now possible to store
and handle complex variant types in a variant easily in a C++ way.
The modified test below exemplifies.
(Variant< std::vector<T> >::create): Create a Variant<> for each of
the members in the vector and then use g_variant_builder_add_value()
to add the underlying GVariant of the wrapped elements in the builder
instead of using the variadic g_variant_builder_add() function which
causes problems when dealing with types that are more complex than
basic ones.
(Variant< std::vector<T> >::get_child): Rewritten to get the child as
a GVariant, wrap the GVariant in a Variant<> and then get its value
instead of assuming that the array in the variant is a fixed array of
basic types so that complex types are supported in arrays.
(Variant< std::vector<T> >::get): Rewritten as get_child() above so
that the elements in the array are gotten as a GVariant, wrapped in a
Variant<> and then retrieved and placed in the resulting vector,
again, to ensure that a vector of complex types can be stored in a
variant.
* tests/glibmm_variant/main.cc: Modify the test to ensure that any
type other than basic ones are supported.
ChangeLog | 27 ++++++++++
glib/src/variant.hg | 118 ++++++++++++++++++++++++++++++++++++-----
tests/glibmm_variant/main.cc | 57 ++++++++++++++++++++-
3 files changed, 186 insertions(+), 16 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index a33a7ea..e673c7c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2012-12-28 Josà Alburquerque <jaalburquerque gmail com>
+
+ Variant: Allow containing complex types in arrays and in variants.
+
+ * glib/src/variant.hg (Variant< Variant<T> >): Add a new class capable
+ of containing any Variant<>. The class is just like
+ Variant<VariantBase> except that with it, it is now possible to store
+ and handle complex variant types in a variant easily in a C++ way.
+ The modified test below exemplifies.
+ (Variant< std::vector<T> >::create): Create a Variant<> for each of
+ the members in the vector and then use g_variant_builder_add_value()
+ to add the underlying GVariant of the wrapped elements in the builder
+ instead of using the variadic g_variant_builder_add() function which
+ causes problems when dealing with types that are more complex than
+ basic ones.
+ (Variant< std::vector<T> >::get_child): Rewritten to get the child as
+ a GVariant, wrap the GVariant in a Variant<> and then get its value
+ instead of assuming that the array in the variant is a fixed array of
+ basic types so that complex types are supported in arrays.
+ (Variant< std::vector<T> >::get): Rewritten as get_child() above so
+ that the elements in the array are gotten as a GVariant, wrapped in a
+ Variant<> and then retrieved and placed in the resulting vector,
+ again, to ensure that a vector of complex types can be stored in a
+ variant.
+ * tests/glibmm_variant/main.cc: Modify the test to ensure that any
+ type other than basic ones are supported.
+
2012-12-28 Kjell Ahlstedt <kjell ahlstedt bredband net>
Gio::Action: Add more documentation of get_state_hint() and get_state().
diff --git a/glib/src/variant.hg b/glib/src/variant.hg
index 19e84f8..1237ee1 100644
--- a/glib/src/variant.hg
+++ b/glib/src/variant.hg
@@ -439,6 +439,50 @@ public:
_WRAP_METHOD(VariantBase get() const, g_variant_get_variant)
};
+/** Specialization of Variant containing a Variant<T>.
+ * @newin{2,36}
+ * @ingroup Variant
+ */
+template<class T>
+class Variant< Variant<T> > : public VariantContainerBase
+{
+public:
+ typedef GVariant* CType;
+ typedef Variant<T> CppType;
+ typedef Variant<CppType> CppContainerType;
+
+ /// Default constructor.
+ Variant< Variant<T> >();
+
+ /** GVariant constructor.
+ * @param castitem The GVariant to wrap.
+ * @param take_a_reference Whether to take an extra reference of the
+ * GVariant or not (not taking one could destroy the GVariant with the
+ * wrapper).
+ * @newin{2,36}
+ */
+ explicit Variant< Variant<T> >(GVariant* castitem, bool take_a_reference = false);
+
+ /** Gets the VariantType.
+ * @return The VariantType.
+ * @newin{2,36}
+ */
+ static const VariantType& variant_type() G_GNUC_CONST;
+
+ /** Creates a new Variant< Variant<T> >.
+ * @param data The value of the new Variant.
+ * @return The new Variant.
+ * @newin{2,36}
+ */
+ static Variant< Variant<T> > create(const Variant<T>& data);
+
+ /** Gets the contents of the Variant.
+ * @return The contents of the Variant.
+ * @newin{2,36}
+ */
+ Variant<T> get() const;
+};
+
/** Specialization of Variant containing a Glib::ustring, for variants of type
* string, bytestring, object path, or signature.
* @newin{2,28}
@@ -899,6 +943,42 @@ _IGNORE(
namespace Glib
{
+/*--------------------Variant< Variant<T> >---------------------*/
+
+template<class T>
+Variant< Variant<T> >::Variant()
+: VariantContainerBase()
+{
+}
+
+template<class T>
+Variant< Variant<T> >::Variant(GVariant* castitem, bool take_a_reference)
+: VariantContainerBase(castitem, take_a_reference)
+{
+}
+
+// static
+template<class T>
+const VariantType& Variant< Variant<T> >::variant_type()
+{
+ return VARIANT_TYPE_VARIANT;
+}
+
+template<class T>
+Variant< Variant<T> > Variant< Variant<T> >::create(const Variant<T>& data)
+{
+ Variant< Variant<T> > result = Variant< Variant<T> >(
+ g_variant_new_variant(const_cast<GVariant*>(data.gobj())));
+ return result;
+}
+
+template<class T>
+Variant<T> Variant< Variant<T> >::get() const
+{
+ GVariant* const gvariant = g_variant_get_variant(gobject_);
+ return Variant<T>(gvariant, true);
+}
+
/*--------------------Variant< std::pair<K, V> >---------------------*/
// static
@@ -970,8 +1050,8 @@ Variant< std::vector<T> >::create(const std::vector<T>& data)
for(typename std::vector<T>::const_iterator iter = data.begin();
iter < data.end(); iter++)
{
- g_variant_builder_add(builder,
- reinterpret_cast<gchar*>(element_variant_type.gobj()), *iter);
+ Glib::Variant<T> variant = Glib::Variant<T>::create(*iter);
+ g_variant_builder_add_value(builder, variant.gobj());
}
// Create the variant using the builder.
@@ -985,29 +1065,37 @@ Variant< std::vector<T> >::create(const std::vector<T>& data)
template<class T>
T Variant< std::vector<T> >::get_child(gsize index) const
{
- gsize n_elements = 0;
+ if(index >= g_variant_n_children(const_cast<GVariant*>(gobj())))
+ throw std::out_of_range(
+ "Variant< std::vector<T> >::get_child(): Index out of bounds.");
- const T* array = reinterpret_cast<const T*>(
- g_variant_get_fixed_array(const_cast<GVariant*>(gobj()), &n_elements,
- sizeof(T)));
+ Glib::Variant<T> variant;
- if(index >= n_elements)
- throw std::out_of_range(
- "Variant< std::vector<T> >::get(): Index out of bounds.");
+ GVariant* gvariant =
+ g_variant_get_child_value(const_cast<GVariant*>(gobj()), index);
- return array[index];
+ variant.init(gvariant);
+ return variant.get();
}
template<class T>
std::vector<T> Variant< std::vector<T> >::get() const
{
- gsize n_elements = 0;
+ std::vector<T> result;
+
+ gsize n_children = g_variant_n_children(const_cast<GVariant*>(gobj()));
- const T* array = reinterpret_cast<const T*>(
- g_variant_get_fixed_array(const_cast<GVariant*>(gobj()), &n_elements,
- sizeof(T)));
+ for(gsize i = 0; i < n_children; i++)
+ {
+ Glib::Variant<T> variant;
+
+ GVariant* gvariant =
+ g_variant_get_child_value(const_cast<GVariant*>(gobj()), i);
+
+ variant.init(gvariant);
+ result.push_back(variant.get());
+ }
- std::vector<T> result(array, array + n_elements);
return result;
}
diff --git a/tests/glibmm_variant/main.cc b/tests/glibmm_variant/main.cc
index 49da1e2..086719f 100644
--- a/tests/glibmm_variant/main.cc
+++ b/tests/glibmm_variant/main.cc
@@ -55,7 +55,7 @@ int main(int, char**)
vec_strings.push_back("a");
Glib::Variant<std::vector<std::string> > variant_vec_strings =
Glib::Variant<std::vector<std::string> >::create(vec_strings);
-
+
//Dict:
typedef std::pair<Glib::ustring, Glib::ustring> TypeDictEntry;
@@ -120,6 +120,61 @@ int main(int, char**)
" in the variant are: " << value << '.' << std::endl;
}
+ //std::vector< std::map< Glib::ustring, Glib::Variant<int> > >
+ typedef std::map< Glib::ustring, Glib::Variant<int> > ComplexDictType;
+
+ ComplexDictType complex_dict1;
+ ComplexDictType complex_dict2;
+
+ for(int i = 0; i < 10; i++)
+ {
+ // Convert integer i to string.
+ std::stringstream ss;
+ ss << i;
+
+ Glib::ustring s = "String " + ss.str();
+
+ Glib::Variant<int> v = Glib::Variant<int>::create(i);
+
+ complex_dict1.insert(
+ std::pair< Glib::ustring, Glib::Variant<int> >("Map 1 " + s, v));
+
+ complex_dict2.insert(
+ std::pair< Glib::ustring, Glib::Variant<int> >("Map 2 " + s, v));
+ }
+
+ typedef std::vector< std::map< Glib::ustring, Glib::Variant<int> > >
+ ComplexVecType;
+
+ ComplexVecType complex_vector;
+ complex_vector.push_back(complex_dict1);
+ complex_vector.push_back(complex_dict2);
+
+ Glib::Variant<ComplexVecType> complex_variant =
+ Glib::Variant<ComplexVecType>::create(complex_vector);
+
+ // This will output the type string aa{sv}.
+ ostr << "The type string of the variant containing a vector of "
+ "dictionaries is: " << std::endl << complex_variant.get_type_string() <<
+ "." << std::endl << std::endl;
+
+ ComplexVecType copy_complex_vector = complex_variant.get();
+
+ for(guint i = 0; i < copy_complex_vector.size(); i++)
+ {
+ ostr << "Printing dictionary # " << i + 1 << ":" << std::endl;
+
+ ComplexDictType map = copy_complex_vector[i];
+
+ for(ComplexDictType::const_iterator iter = map.begin();
+ iter != map.end(); iter++)
+ {
+ std::pair< Glib::ustring, Glib::Variant<int> > entry = *iter;
+ ostr << entry.first << " -> " << entry.second.get() << "." << std::endl;
+ }
+ ostr << std::endl;
+ }
+
test_variant_floating();
test_dynamic_cast();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]