[glibmm] Add Variant< std::vector<[Glib::ustring|std::string]> specializations.



commit c7b7eb5f031c9af764171d071ec764f1f4d65b12
Author: José Alburquerque <jaalburqu svn gnome org>
Date:   Tue Dec 21 19:54:48 2010 -0500

    Add Variant< std::vector<[Glib::ustring|std::string]> specializations.
    
    	* glib/src/variant.{ccg,hg}: Add two Variant specializations to deal
    	specifically with arrays of UTF8 and non-UTF8 strings both reflecting
    	the API of the specialization that deals with regular arrays.
    	(docs, typos): Minor corrections.
    	(Variant<std::vector<T>>::get): Have the method that gets the vector
    	return the vector instead of setting an output parameter because
    	returning the vector on the call stack should not be costly and it's
    	probably more intuitive for the programmer.
    	* tests/glibmm_variant/main.cc: Adapt test according to the above
    	change.  Correct minor typos.

 ChangeLog                    |   15 ++++
 glib/src/variant.ccg         |  166 ++++++++++++++++++++++++++++++++++++++++++
 glib/src/variant.hg          |  153 ++++++++++++++++++++++++++++++++++++---
 tests/glibmm_variant/main.cc |   14 ++--
 4 files changed, 330 insertions(+), 18 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 7f57066..c23ebeb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2010-12-21  José Alburquerque  <jaalburqu svn gnome org>
+
+	Add Variant< std::vector<[Glib::ustring|std::string]> specializations.
+
+	* glib/src/variant.{ccg,hg}: Add two Variant specializations to deal
+	specifically with arrays of UTF8 and non-UTF8 strings both reflecting
+	the API of the specialization that deals with regular arrays.
+	(docs, typos): Minor corrections.
+	(Variant<std::vector<T>>::get): Have the method that gets the vector
+	return the vector instead of setting an output parameter because
+	returning the vector on the call stack should not be costly and it's
+	probably more intuitive for the programmer.
+	* tests/glibmm_variant/main.cc: Adapt test according to the above
+	change.  Correct minor typos.
+
 2010-12-20  José Alburquerque  <jaalburqu svn gnome org>
 
 	Allow giomm to build under mingw32.
diff --git a/glib/src/variant.ccg b/glib/src/variant.ccg
index 1590c25..be39d52 100644
--- a/glib/src/variant.ccg
+++ b/glib/src/variant.ccg
@@ -153,4 +153,170 @@ std::string Variant<std::string>::get() const
   return std::string(g_variant_get_bytestring(gobject_));
 }
 
+typedef std::vector<Glib::ustring> type_vec_ustring;
+
+// static
+const VariantType& Variant<type_vec_ustring>::variant_type()
+{
+  static VariantType type(G_VARIANT_TYPE_STRING_ARRAY);
+  return type;
+}
+
+Variant<type_vec_ustring>
+Variant<type_vec_ustring>::create(const type_vec_ustring& data)
+{
+  // Get the variant type of the elements.
+  VariantType element_variant_type = Variant<Glib::ustring>::variant_type();
+
+  // Get the variant type of the array.
+  VariantType array_variant_type =
+    VariantType::create_array(element_variant_type);
+
+  // Create a GVariantBuilder to build the array.
+  GVariantBuilder* builder = g_variant_builder_new(array_variant_type.gobj());
+
+  // Add the elements of the vector into the builder.
+  for(typename type_vec_ustring::const_iterator iter = data.begin();
+   iter < data.end(); iter++)
+  {
+    g_variant_builder_add(builder,
+      reinterpret_cast<gchar*>(element_variant_type.gobj()), iter->c_str());
+  }
+
+  // Create the variant using the builder.
+  Variant<type_vec_ustring> result =
+    Variant<type_vec_ustring>(g_variant_new(
+      reinterpret_cast<gchar*>(array_variant_type.gobj()), builder));
+
+  // Remove the floating reference (since it is newly created).
+  g_variant_ref_sink(result.gobj());
+
+  return result;
+}
+
+Glib::ustring Variant<type_vec_ustring>::get(gsize index) const
+{
+  gsize n_elements = 0;
+
+  const gchar** array = g_variant_get_strv(const_cast<GVariant*>(gobj()),
+    &n_elements);
+
+  if(index > n_elements)
+    throw std::runtime_error(
+      "Variant< std::vector<Glib::ustring >::get(): Index out of bounds.");
+
+  return array[index];
+}
+
+type_vec_ustring Variant<type_vec_ustring>::get() const
+{
+  gsize n_elements = 0;
+
+  const gchar** array = g_variant_get_strv(const_cast<GVariant*>(gobj()),
+    &n_elements);
+
+  type_vec_ustring result(array, array + n_elements);
+  return result;
+}
+
+VariantIter Variant<type_vec_ustring>::get_iter()
+{
+  // Get the variant type of the elements.
+  VariantType element_variant_type = Variant<Glib::ustring>::variant_type();
+
+  // Get the variant type of the array.
+  VariantType array_variant_type =
+    VariantType::create_array(element_variant_type);
+
+  // Get the GVariantIter.
+  GVariantIter* g_iter = 0;
+  g_variant_get(const_cast<GVariant*>(gobj()),
+    reinterpret_cast<gchar*>(array_variant_type.gobj()), &g_iter);
+
+  return VariantIter(g_iter);
+}
+
+typedef std::vector<std::string> type_vec_string;
+
+// static
+const VariantType& Variant<type_vec_string>::variant_type()
+{
+  static VariantType type(G_VARIANT_TYPE_BYTESTRING_ARRAY);
+  return type;
+}
+
+Variant<type_vec_string>
+Variant<type_vec_string>::create(const type_vec_string& data)
+{
+  // Get the variant type of the elements.
+  VariantType element_variant_type = Variant<std::string>::variant_type();
+
+  // Get the variant type of the array.
+  VariantType array_variant_type =
+    VariantType::create_array(element_variant_type);
+
+  // Create a GVariantBuilder to build the array.
+  GVariantBuilder* builder = g_variant_builder_new(array_variant_type.gobj());
+
+  // Add the elements of the vector into the builder.
+  for(typename type_vec_string::const_iterator iter = data.begin();
+   iter < data.end(); iter++)
+  {
+    g_variant_builder_add(builder,
+      reinterpret_cast<gchar*>(element_variant_type.gobj()), iter->c_str());
+  }
+
+  // Create the variant using the builder.
+  Variant<type_vec_string> result =
+    Variant<type_vec_string>(g_variant_new(
+      reinterpret_cast<gchar*>(array_variant_type.gobj()), builder));
+
+  // Remove the floating reference (since it is newly created).
+  g_variant_ref_sink(result.gobj());
+
+  return result;
+}
+
+std::string Variant<type_vec_string>::get(gsize index) const
+{
+  gsize n_elements = 0;
+
+  const gchar** array = g_variant_get_strv(const_cast<GVariant*>(gobj()),
+    &n_elements);
+
+  if(index > n_elements)
+    throw std::runtime_error(
+      "Variant< std::vector<std::string >::get(): Index out of bounds.");
+
+  return array[index];
+}
+
+type_vec_string Variant<type_vec_string>::get() const
+{
+  gsize n_elements = 0;
+
+  const gchar** array = g_variant_get_strv(const_cast<GVariant*>(gobj()),
+    &n_elements);
+
+  type_vec_string result(array, array + n_elements);
+  return result;
+}
+
+VariantIter Variant<type_vec_string>::get_iter()
+{
+  // Get the variant type of the elements.
+  VariantType element_variant_type = Variant<std::string>::variant_type();
+
+  // Get the variant type of the array.
+  VariantType array_variant_type =
+    VariantType::create_array(element_variant_type);
+
+  // Get the GVariantIter.
+  GVariantIter* g_iter = 0;
+  g_variant_get(const_cast<GVariant*>(gobj()),
+    reinterpret_cast<gchar*>(array_variant_type.gobj()), &g_iter);
+
+  return VariantIter(g_iter);
+}
+
 } // namespace Glib
diff --git a/glib/src/variant.hg b/glib/src/variant.hg
index eaaf445..abfd3fe 100644
--- a/glib/src/variant.hg
+++ b/glib/src/variant.hg
@@ -351,7 +351,8 @@ public:
   _IGNORE(g_variant_get_string, g_variant_dup_string)
 };
 
-/** Specialization of Glib::Variant containing a std::string.
+/** Specialization of Glib::Variant containing a std::string (a non-capable
+ * UTF8 string).
  * @newin{2,28}
  * @ingroup glibmmVariant
  */
@@ -429,15 +430,15 @@ public:
    */
   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> >.
+  /** Creates a new Glib::Variant from an array of numeric types.
+   * @param data The array to use for creation.
+   * @return The new Glib::Variant.
    * @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
+  /** 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().
    *
@@ -449,14 +450,143 @@ public:
    */
   T get(gsize index) const;
 
-  /** Gets the vector of the Glib::Variant< std::vector<T> >.
+  /** Gets the vector of the Glib::Variant.
    * @return The vector.
    * @newin{2,28}
    */
-  void get(std::vector<T>& result) const;
+  std::vector<T> get() const;
   _IGNORE(g_variant_get_fixed_array)
 
-  /** Gets a VariantIter of the contained array.
+  /** Gets a VariantIter of the Variant.
+   * @return the VaraintIter.
+   * @newin{2,28}
+   */
+  VariantIter get_iter();
+};
+
+/** Specialization of Glib::Variant containing an array of UTF-8 capable
+ * strings.
+ */
+template<>
+class Variant< std::vector<Glib::ustring> > : public VariantContainerBase
+{
+public:
+  typedef Glib::ustring                 CppType;
+  typedef std::vector<Glib::ustring>    CppContainerType;
+
+  /// Default constructor.
+  Variant< std::vector<Glib::ustring> >()
+  : VariantContainerBase()
+  {}
+
+  /** 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).
+   */
+  explicit Variant< std::vector<Glib::ustring> >(GVariant* castitem,
+    bool take_a_reference = false)
+  : VariantContainerBase(castitem, take_a_reference)
+  {}
+
+  /** 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 from an array of strings.
+   * @param data The array to use for creation.
+   * @return The new Glib::Variant.
+   * @newin{2,28}
+   */
+  static Variant< std::vector<Glib::ustring> >
+    create(const std::vector<Glib::ustring>& data);
+
+  /** Gets a specific element of the string 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}
+   */
+  Glib::ustring get(gsize index) const;
+
+  /** Gets the string vector of the Glib::Variant.
+   * @return The vector.
+   * @newin{2,28}
+   */
+  std::vector<Glib::ustring> get() const;
+
+  /** Gets a VariantIter of the Variant.
+   * @return the VaraintIter.
+   * @newin{2,28}
+   */
+  VariantIter get_iter();
+};
+
+/** Specialization of Glib::Variant containing an array of non-UTF8 strings.
+ */
+template<>
+class Variant< std::vector<std::string> > : public VariantContainerBase
+{
+public:
+  typedef std::string                   CppType;
+  typedef std::vector<std::string>      CppContainerType;
+
+  /// Default constructor.
+  Variant< std::vector<std::string> >()
+  : VariantContainerBase()
+  {}
+
+  /** 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).
+   */
+  explicit Variant< std::vector<std::string> >(GVariant* castitem,
+    bool take_a_reference = false)
+  : VariantContainerBase(castitem, take_a_reference)
+  {}
+
+  /** 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 from an array of strings.
+   * @param data The array to use for creation.
+   * @return The new Glib::Variant.
+   * @newin{2,28}
+   */
+  static Variant< std::vector<std::string> >
+    create(const std::vector<std::string>& data);
+
+  /** Gets a specific element of the string 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}
+   */
+  std::string get(gsize index) const;
+
+  /** Gets the string vector of the Glib::Variant.
+   * @return The vector.
+   * @newin{2,28}
+   */
+  std::vector<std::string> get() const;
+
+  /** Gets a VariantIter of the Variant.
    * @return the VaraintIter.
    * @newin{2,28}
    */
@@ -543,13 +673,13 @@ T Variant< std::vector<T> >::get(gsize index) const
 
   if(index > n_elements)
     throw std::runtime_error(
-      "T Variant< std::vector<T> > get(): Index out of bounds.");
+      "Variant< std::vector<T> >::get(): Index out of bounds.");
 
   return array[index];
 }
 
 template<class T>
-void Variant< std::vector<T> >::get(std::vector<T>& result) const
+std::vector<T> Variant< std::vector<T> >::get() const
 {
   gsize n_elements = 0;
 
@@ -557,7 +687,8 @@ void Variant< std::vector<T> >::get(std::vector<T>& result) const
     g_variant_get_fixed_array(const_cast<GVariant*>(gobj()), &n_elements,
     sizeof(T)));
 
-  result.assign(array, array + n_elements);
+  std::vector<T> result(array, array + n_elements);
+  return result;
 }
 
 template<class T>
diff --git a/tests/glibmm_variant/main.cc b/tests/glibmm_variant/main.cc
index 75038ad..71d3bbd 100644
--- a/tests/glibmm_variant/main.cc
+++ b/tests/glibmm_variant/main.cc
@@ -18,9 +18,7 @@ int main(int, char**)
   Glib::Variant< std::vector<int> > integers_variant =
     Glib::Variant< std::vector<int> >::create(int_vector);
 
-  std::vector<int> int_vector2;
-
-  integers_variant.get(int_vector2);
+  std::vector<int> int_vector2 = integers_variant.get();
 
   std::cout << "The size of the copied vector is " << int_vector2.size() <<
     '.' << std::endl;
@@ -30,11 +28,13 @@ int main(int, char**)
   for(guint i = 0; i < int_vector2.size(); i++)
     std::cout << int_vector2[i] << std::endl;
 
-  std::cout << "The number of children in the iterator of the copy are " <<
-    integers_variant.get_iter().get_n_children() << '.' << std::endl;
+  std::cout << "The number of children in the iterator of the " <<
+    "variant are " << integers_variant.get_iter().get_n_children() <<
+    '.' << std::endl;
 
-  std::cout << "The 5th element in the copy is " <<
-    integers_variant.get(5) << '.' << std::endl;
+  int index = 4;
+  std::cout << "Element number " << index + 1 << " in the copy is " <<
+    integers_variant.get(index) << '.' << std::endl;
 
   return 0;
 }



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