[glibmm] Added a new Glib::Variant<> specialization to deal with arrays.



commit abff30a5fadb81335f969e8839b946fbacc024a5
Author: José Alburquerque <jaalburqu svn gnome org>
Date:   Thu Dec 16 19:37:41 2010 -0500

    	Added a new Glib::Variant<> specialization to deal with arrays.
    
    	* glib/src/variant.{ccg,hg} (VariantBase::get_maybe): Move the method
    	that gets a maybe of a container to Variant<VariantBase> because it a
    	container specific method.
    	(Variant<VariantBase>::get): Correct this method so that it uses an
    	output parameter instead of returning a VariantBase.
    	(Variant< std::vector<T> >): Added a new specialization designed to
    	deal with variant arrays. Similar types dealing with array of strings
    	should also be added.
    	(typedefs): Added some typedefs that might possibly be useful later.
    	(docs): Added docs to methods without them.
    	* glib/src/variant_basictypes.{cc,h}.m4:
    	(variant_type): Made all the static variant_type() methods return a
    	Glib::VariantType so the C++ wrapper is used.
    	* glib/src/variantiter.{ccg,hg}: Corrected the includes so
    	variantiter.h can be included in variant.h.

 ChangeLog                         |   20 +++
 glib/src/variant.ccg              |   51 ++++----
 glib/src/variant.hg               |  245 +++++++++++++++++++++++++++++++++++--
 glib/src/variant_basictypes.cc.m4 |    5 +-
 glib/src/variant_basictypes.h.m4  |    6 +-
 glib/src/variantiter.ccg          |    2 +
 glib/src/variantiter.hg           |    5 +-
 7 files changed, 293 insertions(+), 41 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 0614956..fd368e1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2010-12-16  José Alburquerque  <jaalburqu svn gnome org>
+
+	Added a new Glib::Variant<> specialization to deal with arrays.
+
+	* glib/src/variant.{ccg,hg} (VariantBase::get_maybe): Move the method
+	that gets a maybe of a container to Variant<VariantBase> because it a
+	container specific method.
+	(Variant<VariantBase>::get): Correct this method so that it uses an
+	output parameter instead of returning a VariantBase.
+	(Variant< std::vector<T> >): Added a new specialization designed to
+	deal with variant arrays. Similar types dealing with array of strings
+	should also be added.
+	(typedefs): Added some typedefs that might possibly be useful later.
+	(docs): Added docs to methods without them.
+	* glib/src/variant_basictypes.{cc,h}.m4:
+	(variant_type): Made all the static variant_type() methods return a
+	Glib::VariantType so the C++ wrapper is used.
+	* glib/src/variantiter.{ccg,hg}: Corrected the includes so
+	variantiter.h can be included in variant.h.
+
 2010-12-15  José Alburquerque  <jaalburqu svn gnome org>
 
 	glibmm: Add a Variant<std::string> specialization.
diff --git a/glib/src/variant.ccg b/glib/src/variant.ccg
index 22f9690..22b0d1e 100644
--- a/glib/src/variant.ccg
+++ b/glib/src/variant.ccg
@@ -17,7 +17,7 @@
 
 #include <glibmm/variant.h>
 #include <glibmm/utility.h>
-#include <glib/gvariant.h>
+#include <glib.h>
 
 namespace Glib
 {
@@ -38,21 +38,6 @@ void VariantBase::byteswap(VariantBase& result) const
   result.init(g_value); // g_value is already referenced.
 }
 
-bool VariantBase::get_maybe(Glib::VariantBase& maybe) const
-{
-  GVariant* const g_value =
-    g_variant_get_maybe(const_cast<GVariant*>(gobj()));
-
-  if(g_value)
-  {
-    maybe.init(g_value); // g_value is already referenced.
-    return true;
-  }
-  else
-    return false;
-}
-
-
 
 /****************** Specializations ***********************************/
 
@@ -67,9 +52,10 @@ void VariantBase::init(const GVariant* cobject, bool take_a_reference)
 }
 
 // static
-const GVariantType* Variant<VariantBase>::variant_type()
+const VariantType& Variant<VariantBase>::variant_type()
 {
-  return G_VARIANT_TYPE_VARIANT;
+  static VariantType type(G_VARIANT_TYPE_VARIANT);
+  return type;
 }
 
 Variant<VariantBase> Variant<VariantBase>::create(const VariantBase& data)
@@ -82,15 +68,31 @@ Variant<VariantBase> Variant<VariantBase>::create(const VariantBase& data)
   return result;
 }
 
-VariantBase Variant<VariantBase>::get() const
+void Variant<VariantBase>::get(VariantBase& child) const
 {
-  return VariantBase(g_variant_get_variant(gobject_));
+  GVariant* const gvariant = g_variant_get_variant(gobject_);
+  child.init(gvariant);
+}
+
+bool Variant<VariantBase>::get_maybe(Glib::VariantBase& maybe) const
+{
+  GVariant* const g_value =
+    g_variant_get_maybe(const_cast<GVariant*>(gobj()));
+
+  if(g_value)
+  {
+    maybe.init(g_value); // g_value is already referenced.
+    return true;
+  }
+  else
+    return false;
 }
 
 // static
-const GVariantType* Variant<Glib::ustring>::variant_type()
+const VariantType& Variant<Glib::ustring>::variant_type()
 {
-  return G_VARIANT_TYPE_STRING;
+  static VariantType type(G_VARIANT_TYPE_STRING);
+  return type;
 }
 
 Variant<Glib::ustring>
@@ -111,9 +113,10 @@ Glib::ustring Variant<Glib::ustring>::get() const
 }
 
 // static
-const GVariantType* Variant<std::string>::variant_type()
+const VariantType& Variant<std::string>::variant_type()
 {
-  return G_VARIANT_TYPE_BYTESTRING;
+  static VariantType type(G_VARIANT_TYPE_BYTESTRING);
+  return type;
 }
 
 Variant<std::string>
diff --git a/glib/src/variant.hg b/glib/src/variant.hg
index 1dc4c08..35037b7 100644
--- a/glib/src/variant.hg
+++ b/glib/src/variant.hg
@@ -19,7 +19,9 @@ _DEFS(glibmm,glib)
 
 #include <glibmmconfig.h>
 #include <glibmm/varianttype.h>
+#include <glibmm/variantiter.h>
 #include <glibmm/ustring.h>
+#include <vector>
 
 namespace Glib
 {
@@ -60,9 +62,6 @@ public:
   _WRAP_METHOD(bool is_container() const, g_variant_is_container)
   _WRAP_METHOD(GVariantClass classify() const, g_variant_classify)
 
-  bool get_maybe(Glib::VariantBase& maybe) const;
-  _IGNORE(g_variant_get_maybe)
-
   _WRAP_METHOD(gsize get_size() const, g_variant_get_size)
   _WRAP_METHOD(gconstpointer get_data(), g_variant_get_data)
   _WRAP_METHOD(void store(gpointer data) const, g_variant_store)
@@ -148,26 +147,56 @@ class Variant<VariantBase> : public VariantBase
   _CLASS_GENERIC(Variant<VariantBase>, GVariant)
 
 public:
-  typedef GVariant* CType;
+  typedef GVariant*                     CType;
+  typedef VariantBase                   CppType;
+  typedef Variant<VariantBase>          CppContainerType;
 
+  /// Default constructor.
   Variant<VariantBase>()
   : VariantBase()
   {}
 
+  /** GVariant constructor.
+   * @param castitem The GVariant to wrap.
+   */
   explicit Variant<VariantBase>(GVariant* castitem)
   : VariantBase(castitem)
   {}
 
-  static const GVariantType* variant_type() G_GNUC_CONST;
-
-  //This must have a create() method because otherwise it would be a copy constructor.
+  /** Gets the Glib::VariantType.
+   * @return The Glib::VariantType.
+   * @newin{2,28}
+   */
+  static const Glib::VariantType& variant_type() G_GNUC_CONST;
+
+  //This must have a create() method because otherwise it would be a copy
+  //constructor.
+  /** Creates a new Glib::Variant<VariantBase>.
+   * @param data The value of the new Glib::Variant<VariantBase>.
+   * @return The new Glib::Variant<VariantBase>.
+   * @newin{2,28}
+   */
   static Variant<VariantBase> create(const Glib::VariantBase& data);
   _IGNORE(g_variant_new_variant)
 
-  VariantBase get() const;
+  /** Gets the child of the Glib::Variant<VariantBase>.
+   * @param child The location in which to store the child.
+   * @newin{2,28}
+   */
+  void get(Glib::VariantBase& child) const;
   _IGNORE(g_variant_get_variant)
 
   _WRAP_METHOD(gsize get_n_children() const, g_variant_n_children)
+
+  /** If this is a maybe-typed instance, extract its value. If the value is
+   * Nothing, then this function returns <tt>0</tt>.
+   *
+   * @param maybe A place in which to return the value (the value may be
+   * <tt>0</tt>).
+   * @newin{2,28}
+   */
+  bool get_maybe(Glib::VariantBase& maybe) const;
+  _IGNORE(g_variant_get_maybe)
 };
 
 /** Specialization of Glib::Variant containing a Glib::ustring.
@@ -180,17 +209,35 @@ class Variant<Glib::ustring> : public VariantBase
 public:
   typedef char* CType;
 
+  /// Default constructor.
   Variant<Glib::ustring>()
   : VariantBase()
   {}
 
+  /** GVariant constructor.
+   * @param castitem The GVariant to wrap.
+   */
   explicit Variant<Glib::ustring>(GVariant* castitem)
   : VariantBase(castitem)
   {}
 
-  static const GVariantType* variant_type() G_GNUC_CONST;
+  /** Gets the Glib::VariantType.
+   * @return The Glib::VariantType.
+   * @newin{2,28}
+   */
+  static const Glib::VariantType& variant_type() G_GNUC_CONST;
+
+  /** Creates a new Glib::Variant<Glib::ustring>.
+   * @param data The value of the new Glib::Variant<Glib::ustring>.
+   * @return The new Glib::Variant<Glib::ustring>.
+   * @newin{2,28}
+   */
   static Variant<Glib::ustring> create(const Glib::ustring& data);
 
+  /** Gets the contents of the Glib::Variant<Glib::ustring>.
+   * @return The contents of the Glib::Variant<Glib::ustring>.
+   * @newin{2,28}
+   */
   Glib::ustring get() const;
   _IGNORE(g_variant_get_string, g_variant_dup_string)
 };
@@ -205,21 +252,100 @@ class Variant<std::string> : public VariantBase
 public:
   typedef char* CType;
 
+  /// Default constructor.
   Variant<std::string>()
   : VariantBase()
   {}
 
+  /** GVariant constructor.
+   * @param castitem The GVariant to wrap.
+   */
   explicit Variant<std::string>(GVariant* castitem)
   : VariantBase(castitem)
   {}
 
-  static const GVariantType* variant_type() G_GNUC_CONST;
+  /** Gets the Glib::VariantType.
+   * @return The Glib::VariantType.
+   * @newin{2,28}
+   */
+  static const Glib::VariantType& variant_type() G_GNUC_CONST;
+
+  /** Creates a new Glib::Variant<std::string>.
+   * @param data The value of the new Glib::Variant<std::string>.
+   * @return The new Glib::Variant<std::string>.
+   * @newin{2,28}
+   */
   static Variant<std::string> create(const std::string& data);
 
+  /** Gets the contents of the Glib::Variant<std::string>.
+   * @return The contents of the Glib::Variant<std::string>.
+   * @newin{2,28}
+   */
   std::string get() const;
   _IGNORE(g_variant_get_bytestring, g_variant_dup_bytestring)
 };
 
+/** Specialization of Glib::Variant containing an array of items.
+ */
+template <class T>
+class Variant< std::vector<T> > : public Variant<VariantBase>
+{
+public:
+  typedef T                     CppType;
+  typedef std::vector<T>        CppContainerType;
+
+  /// Default constructor.
+  Variant< std::vector<T> >()
+  : Variant<VariantBase>()
+  {}
+
+  /** GVariant constructor.
+   * @param castitem The GVariant to wrap.
+   */
+  explicit Variant< std::vector<T> >(GVariant* castitem)
+  : Variant<VariantBase>(castitem)
+  {}
+
+  /** Gets the Glib::VariantType.
+   * @return The Glib::VariantType.
+   * @newin{2,28}
+   */
+  static const Glib::VariantType& variant_type() G_GNUC_CONST;
+
+  /** Creates a new Glib::Variant< std::vector<T> > (a variant array).
+   * @param data The array of the new Glib::Variant< std::vector<T> >.
+   * @return The new Glib::Variant< std::vector<T> >.
+   * @newin{2,28}
+   */
+  static Variant< std::vector<T> > create(const std::vector<T>& data);
+  _IGNORE(g_variant_new_array)
+
+  /** Gets a specific element of the array.  It is an error if index_ is
+   * greater than the number of child items in the container.  See
+   * Glib::Variant<VariantBase>::n_children().
+   *
+   * This function is O(1).
+   *
+   * @param index The index of the element.
+   * @return The element at index @index.
+   * @newin{2,28}
+   */
+  T get(gsize index) const;
+
+  /** Gets the vector of the Glib::Variant< std::vector<T> >.
+   * @return The vector.
+   * @newin{2,28}
+   */
+  std::vector<T> get() const;
+  _IGNORE(get_variant_get_fixed_array)
+
+  /** Gets a VariantIter of the contained array.
+   * @return the VaraintIter.
+   * @newin{2,28}
+   */
+  VariantIter get_iter();
+};
+
 } // namespace Glib
 
 
@@ -242,3 +368,102 @@ _IGNORE(
 #define _GLIBMM_VARIANT_H_INCLUDE_VARIANT_BASICTYPES_H
 #include <glibmm/variant_basictypes.h>
 #undef _GLIBMM_VARIANT_H_INCLUDE_VARIANT_BASICTYPES_H
+
+namespace Glib
+{
+
+/*-----------------------Glib::Variant< std::vector<T> --------------------*/
+
+// static
+template<class T>
+const VariantType& Variant< std::vector<T> >::variant_type()
+{
+  static VariantType type(G_VARIANT_TYPE_ARRAY);
+  return type;
+}
+
+template<class T>
+Variant< std::vector<T> >
+Variant< std::vector<T> >::create(const  std::vector<T>& data)
+{
+  // Get the variant type of the elements as a string.
+  std::string element_variant_type =
+    static_cast<char*>(Variant<T>::variant_type().gobj());
+
+  // Get the variant type of the array as a string.
+  std::string array_variant_type = "a" + element_variant_type;
+
+  // Create a GVariantBuilder to build the array.
+  GVariantBuilder* builder =
+    g_variant_builder_new(G_VARIANT_TYPE(array_variant_type.c_str()));
+
+  // Add the elements of the vector into the builder.
+  for(typename std::vector<T>::iterator iter = data.begin(); iter < data.end();
+    iter++)
+  {
+    g_variant_builder_add(builder, element_variant_type, *iter);
+  }
+
+  // Create the variant using the builder.
+  Variant< std::vector<T> > result =
+    Variant< std::vector<T> >(g_variant_new(array_variant_type.c_str(),
+    builder));
+
+  // Remove the floating reference (since it is newly created).
+  g_variant_ref_sink(result.gobj());
+
+  return result;
+}
+
+template<class T>
+T Variant< std::vector<T> >::get(gsize index) const
+{
+  GVariant* gvariant = g_variant_get_child_value(gobj(), index);
+  Glib::Variant<T> variant(gvariant, true /* take extra ref to preserve */);
+  return variant.get();
+}
+
+template<class T>
+std::vector<T> Variant< std::vector<T> >::get() const
+{
+  // Get the variant type of the elements as a string.
+  std::string element_variant_type =
+    static_cast<char*>(Variant<T>::variant_type().gobj());
+
+  // Get the variant type of the array as a string.
+  std::string array_variant_type = "a" + element_variant_type;
+
+  // Get the GVariantIter.
+  GVariantIter* g_iter = 0;
+  g_variant_get(gobj(), array_variant_type.c_str(), &g_iter);
+
+  // Wrap the GVariantIter.
+  VariantIter iter(g_iter);
+
+  std::vector<T> result;
+  Glib::Variant<T> element;
+
+  while(iter.next_value(element))
+    result.push_back(element.get());
+
+  return result;
+}
+
+template<class T>
+VariantIter Variant< std::vector<T> >::get_iter()
+{
+  // Get the variant type of the elements as a string.
+  std::string element_variant_type =
+    static_cast<char*>(Variant<T>::variant_type().gobj());
+
+  // Get the variant type of the array as a string.
+  std::string array_variant_type = "a" + element_variant_type;
+
+  // Get the GVariantIter.
+  GVariantIter* g_iter = 0;
+  g_variant_get(gobj(), array_variant_type.c_str(), &g_iter);
+
+  return VariantIter(g_iter);
+}
+
+} // namespace Glib
diff --git a/glib/src/variant_basictypes.cc.m4 b/glib/src/variant_basictypes.cc.m4
index 9dea5f2..1b54ac1 100644
--- a/glib/src/variant_basictypes.cc.m4
+++ b/glib/src/variant_basictypes.cc.m4
@@ -36,9 +36,10 @@ dnl Please ignore the format stuff.  I was just tired and played a little.
 /**** Glib::Variant<$1> translit(format([%]eval(57-len([$1]))[s],[****/]),[ ],[*])
 
 // static
-const GVariantType* Variant<$1>::variant_type()
+const VariantType& Variant<$1>::variant_type()
 {
-  return G_VARIANT_TYPE_[]UPPER($3);
+  static VariantType type(G_VARIANT_TYPE_[]UPPER($3));
+  return type;
 }
 
 Variant<$1> Variant<$1>::create($1 data)
diff --git a/glib/src/variant_basictypes.h.m4 b/glib/src/variant_basictypes.h.m4
index ee0662d..4a095da 100644
--- a/glib/src/variant_basictypes.h.m4
+++ b/glib/src/variant_basictypes.h.m4
@@ -54,10 +54,10 @@ public:
   : VariantBase(castitem)
   {}
 
-  /** Gets the GVariantType.
-   * @return The GVariantType.
+  /** Gets the Glib::VariantType.
+   * @return The Glib::VariantType.
    */
-  static const GVariantType* variant_type() G_GNUC_CONST;
+  static const VariantType& variant_type() G_GNUC_CONST;
 
   /** Creates a new Glib::Variant<$1>.
    * @param data The value of the new Glib::Variant<$1>.
diff --git a/glib/src/variantiter.ccg b/glib/src/variantiter.ccg
index bf3502c..6c20ac9 100644
--- a/glib/src/variantiter.ccg
+++ b/glib/src/variantiter.ccg
@@ -15,6 +15,8 @@
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <glibmm/variant.h>
+#include <glib.h>
 
 namespace Glib
 {
diff --git a/glib/src/variantiter.hg b/glib/src/variantiter.hg
index 8ea6dac..7f38a77 100644
--- a/glib/src/variantiter.hg
+++ b/glib/src/variantiter.hg
@@ -15,13 +15,14 @@
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <glibmm/variant.h>
-
+#include <glib.h>
 _DEFS(glibmm,glib)
 
 namespace Glib
 {
 
+class VariantBase;
+
 //This can't be like a real iterator (like Gtk::TextIter),
 //because g_iter_value_get_next_value() both gets a value and changes the iterator.
 //GtkTextIter allows us to go forward and then separately get the current value.



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]