// -*- 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/ustring.h>

namespace Glib
{

/** @defgroup glibmmVariant Variant Datatype
 *
 * Glib::Variant<> are specialized classes that deal with strongly typed
 * variant data.  They are used to wrap glib's GVariant API.  For more
 * information see the <a
 * href="http://library.gnome.org/devel/glib/stable/glib-GVariant.html">glib
 * variant
 * API</a>.
 */

/** The base class used to wrap glib's GVariant API.
 * @newin{2,26}
 * @ingroup glibmmVariant
 */
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;

  bool get_maybe(Glib::VariantBase& maybe) const;
  

  //TODO: Somehow put this method only in specializations that use container types?:
  
  /** 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;

  
  /** 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
   * Glib::variant_normalise() 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().
   * 
   * 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 Glib::variant_create_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;
   

};

/** Template class from which other Glib::Variant<> specializations derive.
 * @newin{2,26}
 * @ingroup glibmmVariant
 */
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 Glib::Variant containing a Glib::VariantBase.
 * @newin{2,26}
 * @ingroup glibmmVariant
 */
template <>
class Variant<VariantBase> : public VariantBase
{
public:
  typedef GVariant* CType;

  Variant<VariantBase>()
  : VariantBase()
  {}

  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.
  static Variant<VariantBase> create(const Glib::VariantBase& data);
  

  VariantBase get() const;
  
};

/** Specialization of Glib::Variant containing a Glib::ustring.
 * @newin{2,26}
 * @ingroup glibmmVariant
 */
template <>
class Variant<Glib::ustring> : public VariantBase
{
public:
  typedef char* CType;

  Variant<Glib::ustring>()
  : VariantBase()
  {}

  explicit Variant<Glib::ustring>(GVariant* castitem)
  : VariantBase(castitem)
  {}

  static const GVariantType* variant_type() G_GNUC_CONST;
  static Variant<Glib::ustring> create(const Glib::ustring& data);

  Glib::ustring get() 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 Glib::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
{

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

