// -*- c++ -*-
// Generated by gtkmmproc -- DO NOT MODIFY!
#ifndef _GLIBMM_VARIANT_H
#define _GLIBMM_VARIANT_H


/* Copyright 2010 The glibmm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */


#include <glibmmconfig.h>
#include <glibmm/varianttype.h>
#include <glibmm/variantiter.h>
#include <glibmm/ustring.h>
#include <utility>
#include <vector>
#include <map>
#include <stdexcept>
#include <typeinfo>

namespace Glib
{

/** @defgroup Variant Variant Data Types
 *
 * The Variant classes deal with strongly typed
 * variant data. A Variant stores a value along with
 * information about the type of that value. The range of possible
 * values is determined by the type. The type system used is VariantType.
 *
 * See the VariantBase class and it's derived types, such as VariantContainerbase,
 * and the Variant<> template type.
 *
 * Variant instances always have a type and a value (which are given
 * at construction time). The type and value of a Variant
 * can never change other than by the Variant itself being
 * destroyed.  A Variant cannot contain a pointer.
 *
 * Variant is heavily optimised for dealing with data in serialised
 * form. It works particularly well with data located in memory-mapped
 * files. It can perform nearly all deserialisation operations in a
 * small constant time, usually touching only a single memory page.
 * Serialised Variant data can also be sent over the network.
 *
 * Variant is largely compatible with D-Bus.  Almost all types of
 * #GVariant instances can be sent over D-Bus.  See VariantType for
 * exceptions.
 *
 * There is a Python-inspired text language for describing Variant
 * values. Variant includes a printer for this language and a parser
 * with type inferencing.</a>.
 */

//TODO: VariantBase class can be copied, so suggest how it can be dynamic casted to
//derived types: See https://bugzilla.gnome.org/show_bug.cgi?id=644146

//TODO: Add this documentation from the API if we are confident of it for the C++ wrapper:
// #GVariant is completely threadsafe.  A #GVariant instance can be
// concurrently accessed in any way from any number of threads without
// problems.
// Note that we don't copy GVariant's documentation about Memory Use because
// it seems easy to get out of sync and people can look at that C documentation if necessary.

/** This is the base class for all Variant types.
 *
 * If the actual type is known at compile-time then you should use a specific
 * Variant<>, such as Variant<int>. Otherwise, you may use get_type(),
 * is_of_type(), or cast_dynamic().
 *
 * @newin{2,28}
 * @ingroup Variant
 */
class VariantBase
{
  public:
#ifndef DOXYGEN_SHOULD_SKIP_THIS
  typedef VariantBase CppObjectType;
  typedef GVariant BaseObjectType;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

  VariantBase();

  // Use make_a_copy=true when getting it directly from a struct.
  explicit VariantBase(GVariant* castitem, bool make_a_copy = false);

  VariantBase(const VariantBase& src);
  VariantBase& operator=(const VariantBase& src);

  ~VariantBase();

  GVariant*       gobj()       { return gobject_; }
  const GVariant* gobj() const { return gobject_; }

  ///Provides access to the underlying C instance. The caller is responsible for freeing it. Use when directly setting fields in structs.
  GVariant* gobj_copy() const;

protected:
  GVariant* gobject_;

private:

  
public:

  /** Replace the underlying GVariant.
   * This is for use by methods that take a VariantBase& as an output
   * parameter.
   *
   * @param cobject The GVariant* obtained from a C function.
   * @param take_a_reference Whether this method should take a reference, for
   * instance if the C function has not given one.
   */
  void init(const GVariant* cobject, bool take_a_reference = false);

  
  /** Determines the type of @a value.
   * 
   * The return value is valid for the lifetime of @a value and must not
   * be freed.
   * 
   * @newin{2,24}
   * @return A VariantType.
   */
  VariantType get_type() const;
  
  /** Returns the type string of @a value.  Unlike the result of calling
   * g_variant_type_peek_string(), this string is nul-terminated.  This
   * string belongs to Variant and must not be freed.
   * 
   * @newin{2,24}
   * @return The type string for the type of @a value.
   */
  std::string get_type_string() const;
  
  /** Checks whether @a value has a floating reference count.
   * 
   * This function should only ever be used to assert that a given variant
   * is or is not floating, or for debug purposes. To acquire a reference
   * to a variant that might be floating, always use g_variant_ref_sink().
   * 
   * See g_variant_ref_sink() for more information about floating reference
   * counts.
   * 
   * @newin{2,26}
   * @return Whether @a value is floating.
   */
  bool is_floating() const;
  
  /** Checks if a value has a type matching the provided type.
   * 
   * @newin{2,24}
   * @param type A VariantType.
   * @return <tt>true</tt> if the type of @a value matches @a type.
   */
  bool is_of_type(const VariantType& type) const;
  
  /** Checks if @a value is a container.
   * @return <tt>true</tt> if @a value is a container.
   */
  bool is_container() const;
  
  /** Classifies @a value according to its top-level type.
   * 
   * @newin{2,24}
   * @return The VariantClass of @a value.
   */
  GVariantClass classify() const;

  
  /** Determines the number of bytes that would be required to store @a value
   * with g_variant_store().
   * 
   * If @a value has a fixed-sized type then this function always returned
   * that fixed size.
   * 
   * In the case that @a value is already in serialised form or the size has
   * already been calculated (ie: this function has been called before)
   * then this function is O(1).  Otherwise, the size is calculated, an
   * operation which is approximately O(n) in the number of values
   * involved.
   * 
   * @newin{2,24}
   * @return The serialised size of @a value.
   */
  gsize get_size() const;
  
  /** Returns a pointer to the serialised form of a Variant instance.
   * The returned data may not be in fully-normalised form if read from an
   * untrusted source.  The returned data must not be freed; it remains
   * valid for as long as @a value exists.
   * 
   * If @a value is a fixed-sized value that was deserialised from a
   * corrupted serialised container then <tt>0</tt> may be returned.  In this
   * case, the proper thing to do is typically to use the appropriate
   * number of nul bytes in place of @a value.  If @a value is not fixed-sized
   * then <tt>0</tt> is never returned.
   * 
   * In the case that @a value is already in serialised form, this function
   * is O(1).  If the value is not already in serialised form,
   * serialisation occurs implicitly and is approximately O(n) in the size
   * of the result.
   * 
   * @newin{2,24}
   * @return The serialised form of @a value, or <tt>0</tt>.
   */
  gconstpointer get_data();
  
  /** Stores the serialised form of @a value at @a data.  @a data should be
   * large enough.  See g_variant_get_size().
   * 
   * The stored data is in machine native byte order but may not be in
   * fully-normalised form if read from an untrusted source.  See
   * g_variant_get_normal_form() for a solution.
   * 
   * This function is approximately O(n) in the size of @a data.
   * 
   * @newin{2,24}
   * @param data The location to store the serialised data at.
   */
  void store(gpointer data) const;

  
  /** Pretty-prints @a value in the format understood by g_variant_parse().
   * 
   * The format is described here.
   * 
   * If @a type_annotate is <tt>true</tt>, then type information is included in
   * the output.
   * @param type_annotate <tt>true</tt> if type information should be included in
   * the output.
   * @return A newly-allocated string holding the result.
   */
  Glib::ustring print(bool type_annotate =  false) const;
  

  /** Generates a hash value for a Variant instance.
   * 
   * The output of this function is guaranteed to be the same for a given
   * value only per-process.  It may change between different processor
   * architectures or even different versions of GLib.  Do not use this
   * function as a basis for building protocols or file formats.
   * 
   * The type of @a value is #gconstpointer only to allow use of this
   * function with HashTable.  @a value must be a Variant.
   * 
   * @newin{2,24}
   * @param value A basic Variant value as a #gconstpointer.
   * @return A hash value corresponding to @a value.
   */
  guint hash() const;
  
  /** Checks if @a one and @a two have the same type and value.
   * 
   * The types of @a one and @a two are #gconstpointer only to allow use of
   * this function with HashTable.  They must each be a Variant.
   * 
   * @newin{2,24}
   * @param one A Variant instance.
   * @param two A Variant instance.
   * @return <tt>true</tt> if @a one and @a two are equal.
   */
  bool equal(const VariantBase& other) const;

  /** Gets a VariantBase instance that has the same value as this variant and
   * is trusted to be in normal form.
   *
   * If this variant is already trusted to be in normal form then a new
   * reference to the variant is returned.
   *
   * If this variant is not already trusted, then it is scanned to check if it
   * is in normal form. If it is found to be in normal form then it is marked
   * as trusted and a new reference to it is returned.
   *
   * If this variant is found not to be in normal form then a new trusted
   * VariantBase is created with the same value as this variant.
   *
   * It makes sense to call this function if you've received variant data from
   * untrusted sources and you want to ensure your serialised output is
   * definitely in normal form.
   *
   * @param result A location in which to store the trusted VariantBase.
   * @newin{2,24}
   */
  void get_normal_form(VariantBase& result) const;
  

  /** Checks if @a value is in normal form.
   * 
   * The main reason to do this is to detect if a given chunk of
   * serialised data is in normal form: load the data into a Variant
   * using g_variant_new_from_data() and then use this function to
   * check.
   * 
   * If @a value is found to be in normal form then it will be marked as
   * being trusted.  If the value was already marked as being trusted then
   * this function will immediately return <tt>true</tt>.
   * 
   * @newin{2,24}
   * @return <tt>true</tt> if @a value is in normal form.
   */
  bool is_normal_form() const;

  /** Performs a byteswapping operation on the contents of this variant. The
   * result is that all multi-byte numeric data contained in the variant is
   * byteswapped. That includes 16, 32, and 64bit signed and unsigned integers
   * as well as file handles and double precision floating point values.
   *
   * This function is an identity mapping on any value that does not contain
   * multi-byte numeric data. That include strings, booleans, bytes and
   * containers containing only these things (recursively).
   *
   * The returned value is always in normal form and is marked as trusted.
   *
   * @param result A location in which to store the byteswapped form of this
   * variant.
   * @newin{2,24}
   */
   void byteswap(VariantBase& result) const;
   

   /** Cast to a specific variant type.
    * For instance:
    * @code
    * Variant<std::string> derived = VariantBase::cast_dynamic< Variant<std::string> >(base);
    * @endcode
    *
    * @param v The variant to cast to a specific type.
    * @result The variant as a specific type.
    * @throws std::bad_cast if the Variant was not of the expected type.
    */
   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()))
  {
    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
 */
class VariantStringBase : public VariantBase
{
  // Trick gmmproc into thinking this is derived from GVariant to wrap a
  // some methods.
  public:
#ifndef DOXYGEN_SHOULD_SKIP_THIS
  typedef VariantStringBase CppObjectType;
  typedef GVariant BaseObjectType;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

private:


public:
  typedef GVariant*                     CType;
  typedef VariantStringBase             CppType;

  /// Default constructor.
  VariantStringBase();

  /** 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 VariantStringBase(GVariant* castitem,  bool take_a_reference = false);

  /** Creates a D-Bus object path variant with the contents of @a string. @a
   * string must be a valid D-Bus object path. Use is_object_path() if unsure.
   *
   * @param output A location in which to store the new object path variant
   * instance.
   * @param object_path A normal nul-terminated string.
   * @newin{2,28}
   */
  static void create_object_path(VariantStringBase& output,
    const std::string& object_path);
  

  /** Determines if a given string is a valid D-Bus object path.  You
   * should ensure that a string is a valid D-Bus object path before
   * passing it to g_variant_new_object_path().
   * 
   * A valid object path starts with '/' followed by zero or more
   * sequences of characters separated by '/' characters.  Each sequence
   * must contain only the characters "[A-Z][a-z][0-9]_".  No sequence
   * (including the one following the final '/' character) may be empty.
   * 
   * @newin{2,24}
   * @param string A normal C nul-terminated string.
   * @return <tt>true</tt> if @a string is a D-Bus object path.
   */
  static bool is_object_path(const std::string& string);

  /** Creates a D-Bus type signature variant with the contents of @a string. @a
   * string must be a valid D-Bus type signature. Use is_signature() if unsure.
   *
   * @param output A location in which to store the new signature variant
   * instance.
   * @param signature A normal nul-terminated string.
   * @newin{2,28}
   */
  static void create_signature(VariantStringBase& output,
    const std::string& object_path);
  

  /** Determines if a given string is a valid D-Bus type signature.  You
   * should ensure that a string is a valid D-Bus type signature before
   * passing it to g_variant_new_signature().
   * 
   * D-Bus type signatures consist of zero or more definite VariantType
   * strings in sequence.
   * 
   * @newin{2,24}
   * @param string A normal C nul-terminated string.
   * @return <tt>true</tt> if @a string is a D-Bus type signature.
   */
  static bool is_signature(const std::string& string);


};

/** The base class from which multiple-item Variants derive, such as Variants
 * containing tuples or arrays.
 *
 * @newin{2,28}
 * @ingroup Variant
 */
class VariantContainerBase : public VariantBase
{
  // Trick gmmproc into thinking this is derived from GVariant to wrap a
  // some methods.
  public:
#ifndef DOXYGEN_SHOULD_SKIP_THIS
  typedef VariantContainerBase CppObjectType;
  typedef GVariant BaseObjectType;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

private:


public:
  typedef GVariant*                     CType;
  typedef VariantContainerBase          CppType;

  /// Default constructor.
  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 VariantContainerBase(GVariant* castitem, bool take_a_reference = false);

  /** Create a tuple variant from a vector of its variant children.
   * @param children The vector containing the children of the container.
   * @return The newly created tuple variant (as a VariantContainerBase).
   */
  static VariantContainerBase create_tuple(const std::vector<VariantBase>& children);

  /** Create a tuple variant with a single variant child.
   * @param child The child variant.
   * @return The newly created tuple variant (as a VariantContainerBase).
   */
  static VariantContainerBase create_tuple(const VariantBase& child);

  
  /** Determines the number of children in a container Variant instance.
   * This includes variants, maybes, arrays, tuples and dictionary
   * entries.  It is an error to call this function on any other type of
   * Variant.
   * 
   * For variants, the return value is always 1.  For values with maybe
   * types, it is always zero or one.  For arrays, it is the length of the
   * array.  For tuples it is the number of tuple items (which depends
   * only on the type).  For dictionary entries, it is always 2
   * 
   * This function is O(1).
   * 
   * @newin{2,24}
   * @return The number of children in the container.
   */
  gsize get_n_children() const;

  /** Reads a child item out of this instance. This method is valid for
   * variants, maybes, arrays, tuples and dictionary entries.
   *
   * It is an error if @a index is greater than the number of child items in
   * the container. See get_n_children().
   *
   * This function is O(1).
   *
   * @param index The index of the child to fetch.
   * @param child A location in which to store the child at the specified
   * index.
   * @throw std::out_of_range
   * @newin{2,28}
   */
  void get_child(VariantBase& child, gsize index = 0) const;
  

  /** Reads a child item out of a container Variant instance.  This
   * includes variants, maybes, arrays, tuples and dictionary
   * entries.  It is an error to call this function on any other type of
   * Variant.
   * 
   * It is an error if @a index is greater than the number of child items
   * in the container.  See g_variant_n_children().
   * 
   * This function is O(1).
   * 
   * @newin{2,24}
   * @param index The index of the child to fetch.
   * @return The child at the specified index.
   */
  VariantBase get_child(gsize index =  0);

  /* TODO?:
  /// A get() method to return the contents of the variant in the container.
  template <class DataType>
  DataType get_child(gsize index = 0) const;
  */

  /** 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(VariantBase& maybe) const;
  

};

template<>
VariantContainerBase VariantBase::cast_dynamic<VariantContainerBase>(const VariantBase& v)
throw(std::bad_cast);

/** Template class used for the specialization of the Variant<> classes.
 * @newin{2,28}
 * @ingroup Variant
 */
template<class T>
class Variant : public VariantBase
{
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.


/****************** Specializations ***********************************/

/** Specialization of Variant containing a VariantBase.
 * @newin{2,28}
 * @ingroup Variant
 */
template<>
class Variant<VariantBase> : public VariantContainerBase
{
  // Trick gmmproc into thinking this is derived from GVariant to wrap a
  // some methods.
  public:
#ifndef DOXYGEN_SHOULD_SKIP_THIS
  typedef Variant<VariantBase> CppObjectType;
  typedef GVariant BaseObjectType;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

private:


public:
  typedef GVariant*                     CType;
  typedef VariantBase                   CppType;
  typedef Variant<VariantBase>          CppContainerType;

  /// Default constructor.
  Variant<VariantBase>();

  /** 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<VariantBase>(GVariant* castitem, bool take_a_reference = false);

  /** Gets the VariantType.
   * @return The VariantType.
   * @newin{2,28}
   */
  static const VariantType& variant_type() G_GNUC_CONST;

  //This must have a create() method because otherwise it would be a copy
  //constructor.
  /** Creates a new Variant<VariantBase>.
   * @param data The value of the new Variant.
   * @return The new Variant.
   * @newin{2,28}
   */
  static Variant<VariantBase> create(const VariantBase& data);
  

  //TODO: Documentation
  void get(VariantBase& variant) const;

  
  /** Unboxes @a value.  The result is the Variant instance that was
   * contained in @a value.
   * 
   * @newin{2,24}
   * @return The item contained in the variant.
   */
  VariantBase get() const;


};

/** Specialization of Variant containing a Glib::ustring, for variants of type
 * string, bytestring, object path, or signature.
 * @newin{2,28}
 * @ingroup Variant
 */
template<>
class Variant<Glib::ustring> : public VariantStringBase
{
  // Trick gmmproc into thinking this is derived from GVariant to wrap a
  // some methods.
  public:
#ifndef DOXYGEN_SHOULD_SKIP_THIS
  typedef Variant<Glib::ustring> CppObjectType;
  typedef GVariant BaseObjectType;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

private:

public:
  typedef char*                 CType;
  typedef Glib::ustring         CppType;

  /// Default constructor.
  Variant<Glib::ustring>();

  /** 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<Glib::ustring>(GVariant* castitem,  bool take_a_reference = false);

  /** Gets the VariantType.
   * @return The VariantType.
   * @newin{2,28}
   */
  static const VariantType& variant_type() G_GNUC_CONST;

  /** Creates a new Variant<Glib::ustring>.
   * @param data The value of the new Variant.
   * @return The new Variant.
   * @newin{2,28}
   */
  static Variant<Glib::ustring> create(const Glib::ustring& data);

  //We can't use WRAP_METHOD() here because g_variant_get_string() takes an extra length parameter.
  /** Gets the contents of the Variant.
   * @return The contents of the Variant.
   * @newin{2,28}
   */
  Glib::ustring get() const;
  

};

template<>
Variant<Glib::ustring> VariantBase::cast_dynamic< Variant<Glib::ustring> >(const VariantBase& v)
throw(std::bad_cast);

/** Specialization of Variant containing a std::string, for variants of type
 * bytestring, object path, or signature.
 * See also Variant<Glib::ustring> for UTF-8 strings.
 * @newin{2,28}
 * @ingroup Variant
 */
template<>
class Variant<std::string> : public VariantStringBase
{
  // Trick gmmproc into thinking this is derived from GVariant to wrap a
  // some methods.
  public:
#ifndef DOXYGEN_SHOULD_SKIP_THIS
  typedef Variant<std::string> CppObjectType;
  typedef GVariant BaseObjectType;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

private:

public:
  typedef char*                 CType;
  typedef std::string           CppType;

  /// Default constructor.
  Variant<std::string>();

  /** 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::string>(GVariant* castitem, bool take_a_reference = false);

  /** Gets the VariantType.
   * @return The VariantType.
   * @newin{2,28}
   */
  static const VariantType& variant_type() G_GNUC_CONST;

  /** Creates a new Variant<std::string>.
   * @param data The value of the new Variant.
   * @return The new Variant.
   * @newin{2,28}
   */
  static Variant<std::string> create(const std::string& data);

  //TODO: Documentation.
  std::string get() const;
  

};

template<>
Variant<std::string> VariantBase::cast_dynamic< Variant<std::string> >(const VariantBase& v)
throw(std::bad_cast);

/** Specialization of Variant containing a dictionary entry.  See also
 * Variant< std::map<K, V> >.
 * @newin{2,28}
 * @ingroup Variant
 */
template<class K, class V>
class Variant< std::pair<K, V> > : public VariantContainerBase
{
public:
  typedef std::pair<K, V>               CppType;
  typedef Variant<CppType>        CppContainerType;

  /// Default constructor.
  Variant< std::pair<K, V> >()
  : 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::pair<K, V> >(GVariant* castitem,
    bool take_a_reference = false)
  : VariantContainerBase(castitem, take_a_reference)
  {}

  /** Gets the VariantType.
   * @return The VariantType.
   * @newin{2,28}
   */
  static const VariantType& variant_type() G_GNUC_CONST;

  /** Creates a new Variant< std::pair<K, V> >.
   * @param data The value of the new Variant.
   * @return The new Variant.
   * @newin{2,28}
   */
  static Variant< std::pair<K, V> > create(const std::pair<K, V>& data);
  

  /** Gets the contents of the Variant.
   * @return The contents of the Variant.
   * @throw std::out_of_range
   * @newin{2,28}
   */
  std::pair<K, V> get() const;
};

/** Specialization of Variant containing an array of items.
 * @newin{2,28}
 * @ingroup Variant
 */
template<class T>
class Variant< std::vector<T> > : public VariantContainerBase
{
public:
  typedef T                     CppType;
  typedef std::vector<T>        CppContainerType;

  /// Default constructor.
  Variant< std::vector<T> >()
  : 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<T> >(GVariant* castitem,
    bool take_a_reference = false)
  : VariantContainerBase(castitem, take_a_reference)
  {}

  /** Gets the VariantType.
   * @return The VariantType.
   * @newin{2,28}
   */
  static const VariantType& variant_type() G_GNUC_CONST;

  /** Creates a new Variant from an array of numeric types.
   * @param data The array to use for creation.
   * @return The new Variant.
   * @newin{2,28}
   */
  static Variant< std::vector<T> > create(const std::vector<T>& data);
  

  /** Gets a specific element of the array.  It is an error if @a index is
   * greater than the number of child items in the container.  See
   * VariantContainerBase::get_n_children().
   *
   * This function is O(1).
   *
   * @param index The index of the element.
   * @return The element at index @index.
   * @throw std::out_of_range
   * @newin{2,28}
   */
  T get_child(gsize index) const;

  /** Gets the vector of the Variant.
   * @return The vector.
   * @newin{2,28}
   */
  std::vector<T> get() const;
  

  /** Gets a VariantIter of the Variant.
   * @return the VaraintIter.
   * @newin{2,28}
   */
  VariantIter get_iter() const;
};

/** Specialization of Variant containing an array of UTF-8 capable
 * strings.
 * @newin{2,28}
 * @ingroup Variant
 */
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> >();

  /** 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);

  /** Gets the VariantType.
   * @return The VariantType.
   * @newin{2,28}
   */
  static const VariantType& variant_type() G_GNUC_CONST;

  /** Creates a new Variant from an array of strings.
   * @param data The array to use for creation.
   * @return The new 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 @a index
   * is greater than the number of child items in the container.  See
   * VariantContainerBase::get_n_children().
   *
   * This function is O(1).
   *
   * @param index The index of the element.
   * @return The element at index @index.
   * @throw std::out_of_range
   * @newin{2,28}
   */
  Glib::ustring get_child(gsize index) const;

  /** Gets the string vector of the 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() const;
};

/** Specialization of Variant containing an array of non-UTF-8 strings
 * (byte string arrays).
 * @newin{2,28}
 * @ingroup Variant
 */
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> >();

  /** 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);

  /** Gets the VariantType.
   * @return The VariantType.
   * @newin{2,28}
   */
  static const VariantType& variant_type() G_GNUC_CONST;

  /** Creates a new Variant from an array of strings.
   * @param data The array to use for creation.
   * @return The new 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 @a index
   * is greater than the number of child items in the container.  See
   * VariantContainerBase::get_n_children().
   *
   * This function is O(1).
   *
   * @param index The index of the element.
   * @return The element at index @index.
   * @throw std::out_of_range
   * @newin{2,28}
   */
  std::string get_child(gsize index) const;

  /** Gets the string vector of the 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}
   */
  VariantIter get_iter() const;
};

/** Specialization of Variant containing a dictionary (a map of (key,
 * value) elements).
 * @newin{2,28}
 * @ingroup Variant
 */
template<class K, class V>
class Variant< std::map<K, V> >: public VariantContainerBase
{
public:
  typedef std::pair<K, V>               CppType;
  typedef std::map<K, V>                CppContainerType;

  /// Default constructor.
  Variant< std::map<K, V> >()
  : 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::map<K, V> >(GVariant* castitem,
    bool take_a_reference = false)
  : VariantContainerBase(castitem, take_a_reference)
  {}

  /** Gets the VariantType.
   * @return The VariantType.
   * @newin{2,28}
   */
  static const VariantType& variant_type() G_GNUC_CONST;

  /** Creates a new Variant containing a dictionary from a map.
   * @param data The map to use for creation.
   * @return The new Variant holding a dictionary.
   * @newin{2,28}
   */
  static Variant< std::map<K, V> > create(const std::map<K, V>& data);

  /** Gets a specific dictionary entry from the string array.  It is an error
   * if @a index is greater than the number of child items in the container.
   * See VariantContainerBase::get_n_children().
   *
   * This function is O(1).
   *
   * @param index The index of the element.
   * @return The dictionary entry at index @index.
   * @throw std::out_of_range
   * @newin{2,28}
   */
  std::pair<K, V> get_child(gsize index) const;

  /** Looks up a value in a dictionary Variant.
   * @param key The key to look up.
   * @param value A location in which to store the value if found.
   * @return <tt>true</tt> if the key is found, <tt>false</tt> otherwise.
   */
  bool lookup(const K& key, V& value) const;
  

  /** Gets the map (the dictionary) of the Variant.
   * @return The vector.
   * @newin{2,28}
   */
  std::map<K, V> get() const;

  /** Gets a VariantIter of the Variant.
   * @return the VaraintIter.
   * @newin{2,28}
   */
  VariantIter get_iter() const;
};

} // namespace Glib


//We ignore g_variant_get_*() methods that are wrapped by Variant<> specializations, such as in variant_basictypes.h.m4.


/* Include generated specializations of Variant<> for fundamental types:
 */
#define _GLIBMM_VARIANT_H_INCLUDE_VARIANT_BASICTYPES_H
#include <glibmm/variant_basictypes.h>
#undef _GLIBMM_VARIANT_H_INCLUDE_VARIANT_BASICTYPES_H

namespace Glib
{

/*--------------------Variant< std::pair<K, V> >---------------------*/

// static
template<class K, class V>
const VariantType& Variant< std::pair<K, V> >::variant_type()
{
  static VariantType type(
    g_variant_type_new_dict_entry(Variant<K>::variant_type().gobj(),
    Variant<V>::variant_type().gobj()));

  return type;
}

template<class K, class V>
Variant< std::pair<K, V> >
Variant< std::pair<K, V> >::create(const std::pair<K, V>& data)
{
  Variant<K> key = Variant<K>::create(data.first);
  Variant<V> value = Variant<V>::create(data.second);

  Variant< std::pair<K, V> > result = Variant< std::pair<K, V> >(
    g_variant_new_dict_entry(key.gobj(), value.gobj()));

  // Remove the floating reference (since it is newly created).
  g_variant_ref_sink(result.gobj());

  return result;
}

template<class K, class V>
std::pair<K, V> Variant< std::pair<K, V> >::get() const
{
  // Get the key (the first element of the this VariantContainerBase).
  Variant<K> key;
  VariantContainerBase::get_child(key, 0);

  // Get the value (the second element of the this VariantContainerBase).
  Variant<V> value;
  VariantContainerBase::get_child(value, 1);

  std::pair<K, V> result(key.get(), value.get());

  return result;
}

/*---------------------Variant< std::vector<T> >---------------------*/

// static
template<class T>
const VariantType& Variant< std::vector<T> >::variant_type()
{
  static VariantType type =
    VariantType::create_array(Variant<T>::variant_type());

  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.
  VariantType element_variant_type = Variant<T>::variant_type();

  // Get the variant type of the array.
  VariantType array_variant_type = Variant< std::vector<T> >::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 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);
  }

  // Create the variant using the builder.
  Variant< std::vector<T> > result =
    Variant< std::vector<T> >(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;
}

template<class T>
T Variant< std::vector<T> >::get_child(gsize index) const
{
  gsize n_elements = 0;

  const T* array = reinterpret_cast<const T*>(
    g_variant_get_fixed_array(const_cast<GVariant*>(gobj()), &n_elements,
    sizeof(T)));

  if(index >= n_elements)
    throw std::out_of_range(
      "Variant< std::vector<T> >::get(): Index out of bounds.");

  return array[index];
}

template<class T>
std::vector<T> Variant< std::vector<T> >::get() const
{
  gsize n_elements = 0;

  const T* array = reinterpret_cast<const T*>(
    g_variant_get_fixed_array(const_cast<GVariant*>(gobj()), &n_elements,
    sizeof(T)));

  std::vector<T> result(array, array + n_elements);
  return result;
}

template<class T>
VariantIter Variant< std::vector<T> >::get_iter() const
{
  // Get the variant type of the elements.
  VariantType element_variant_type = Variant<T>::variant_type();

  // Get the variant type of the array.
  VariantType array_variant_type = Variant< std::vector<T> >::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);
}

/*---------------------Variant< std::map<K, V> > --------------------*/

// static
template<class K, class V>
const VariantType& Variant< std::map<K, V> >::variant_type()
{
  static VariantType type =
    VariantType::create_array(Variant< std::pair<K, V> >::variant_type());

  return type;
}

template<class K, class V>
Variant< std::map<K, V> >
Variant< std::map<K, V> >::create(const std::map<K, V>& data)
{
  // Get the variant type of the elements.
  VariantType element_variant_type =
    Variant< std::pair<K, V> >::variant_type();

  // Get the variant type of the array.
  VariantType array_variant_type = Variant< std::map<K, V> >::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 std::map<K, V>::const_iterator iter = data.begin();
    iter != data.end(); iter++)
  {
    Variant< std::pair<K, V> > dict_entry =
      Variant< std::pair<K, V> >::create(*iter);

    g_variant_builder_add_value(builder, dict_entry.gobj());
  }

  // Create the variant using the builder.
  Variant< std::map<K, V> > result = Variant< std::map<K, V> >(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;
}

template<class K, class V>
std::pair<K, V>
Variant< std::map<K, V> >::get_child(gsize index) const
{
  Variant< std::pair<K, V> > dict_entry;
  VariantContainerBase::get_child(dict_entry, index);
  return dict_entry.get();
}

template<class K, class V>
bool Variant< std::map<K, V> >::lookup(const K& key, V& value) const
{
  // The code in this method pretty much reflects the g_variant_lookup_value()
  // function except that it's more general to deal with keys that are not
  // just strings.
  VariantIter iter = get_iter();

  Variant< std::pair<K, V> > entry;

  while(iter.next_value(entry))
  {
    std::pair<K, V> element = entry.get();

    if(element.first == key)
    {
      value = element.second;
      return true;
    }
  }

  return false;
}

template<class K, class V>
std::map<K, V> Variant< std::map<K, V> >::get() const
{
  std::map<K, V> result;
  VariantIter iter = get_iter();
  Variant< std::pair<K, V> > entry;

  while(iter.next_value(entry))
  {
    result.insert(entry.get());
  }

  return result;
}

template<class K, class V>
VariantIter Variant< std::map<K, V> >::get_iter() const
{
  // Get the variant type of the elements.
  VariantType element_variant_type =
    Variant< std::pair<K, V> >::variant_type();

  // Get the variant type of the array.
  VariantType array_variant_type = Variant< std::map<K, V> >::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


namespace Glib
{

  /** A Glib::wrap() method for this object.
   * 
   * @param object The C instance.
   * @param take_copy False if the result should take ownership of the C instance. True if it should take a new copy or ref.
   * @result A C++ instance that wraps this C instance.
   *
   * @relates Glib::VariantBase
   */
Glib::VariantBase wrap(GVariant* object, bool take_copy = false);

} // namespace Glib


#endif /* _GLIBMM_VARIANT_H */

