context: // Copyright (c) 2011 Novell, Inc.
  //
  // This program is free software; you can redistribute it and/or
  // modify it under the terms of version 2 of the Lesser GNU General 
  // Public License as published by the Free Software Foundation.
  //
  // This program 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 program; if not, write to the
  // Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  // Boston, MA 02111-1307, USA.
  
  using System;
  using System.Runtime.InteropServices;
  using System.Collections.Generic;
  
  namespace GLib {
  
  	public class Variant : IDisposable {
  
  		IntPtr handle;
  		public IntPtr Handle {
  			get { return handle; }
  		}
  
  		// Docs say that GVariant is threadsafe.
  		~Variant ()
  		{
  			Dispose (false);
  		}
  
  		public void Dispose ()
  		{
  			Dispose (true);
  		}
  
  		[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
  		static extern void g_variant_unref (IntPtr handle);
  
  		void Dispose (bool disposing)
  		{
  			if (handle == IntPtr.Zero)
  				return;
  
  			g_variant_unref (handle);
  			handle = IntPtr.Zero;
  			if (disposing)
  				GC.SuppressFinalize (this);
  		}
  
  		[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
  		static extern IntPtr g_variant_ref_sink (IntPtr handle);
  
  		public Variant (IntPtr handle)
  		{
  			this.handle = g_variant_ref_sink (handle);
  		}
  
  		[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
  		static extern IntPtr g_variant_get_type (IntPtr val);
  
  		VariantType type;
  		public VariantType Type {
  			get {
  				if (type == null)
  					type = new VariantType (g_variant_get_type (Handle));
  				return type;
  			}
  		}
  
  		[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
  		static extern IntPtr g_variant_new_variant (IntPtr val);
  
  		public static Variant NewVariant (Variant val) {
  			return new Variant (g_variant_new_variant (val.Handle));
  		}
  
  		[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
  		static extern IntPtr g_variant_new_boolean (bool val);
  
  		public Variant (bool val) : this (g_variant_new_boolean (val)) {}
  
  		[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
  		static extern IntPtr g_variant_new_byte (byte val);
  
  		public Variant (byte val) : this (g_variant_new_byte (val)) {}
  
  		[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
  		static extern IntPtr g_variant_new_int16 (short val);
  
  		public Variant (short val) : this (g_variant_new_int16 (val)) {}
  
  		[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
  		static extern IntPtr g_variant_new_uint16 (ushort val);
  
  		public Variant (ushort val) : this (g_variant_new_uint16 (val)) {}
  
  		[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
  		static extern IntPtr g_variant_new_int32 (int val);
  
  		public Variant (int val) : this (g_variant_new_int32 (val)) {}
  
  		[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
  		static extern IntPtr g_variant_new_uint32 (uint val);
  
  		public Variant (uint val) : this (g_variant_new_uint32 (val)) {}
  
  		[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
  		static extern IntPtr g_variant_new_int64 (long val);
  
  		public Variant (long val) : this (g_variant_new_int64 (val)) {}
  
  		[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
  		static extern IntPtr g_variant_new_uint64 (ulong val);
  
  		public Variant (ulong val) : this (g_variant_new_uint64 (val)) {}
  
  		[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
  		static extern IntPtr g_variant_new_double (double val);
  
  		public Variant (double val) : this (g_variant_new_double (val)) {}
  
  		[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
  		static extern IntPtr g_variant_new_string (IntPtr val);
  
  		public Variant (string val)
  		{
  			IntPtr native_val = Marshaller.StringToPtrGStrdup (val);
  			handle = g_variant_ref_sink (g_variant_new_string (native_val));
  			Marshaller.Free (native_val);
  		}
  
  		[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
  		static extern IntPtr g_variant_new_strv (IntPtr[] strv, IntPtr length);
  
  		public Variant (string[] strv)
  		{
  			IntPtr[] native = Marshaller.StringArrayToNullTermPointer (strv);
  			handle = g_variant_ref_sink (g_variant_new_strv (native, new IntPtr ((long) strv.Length)));
  			Marshaller.Free (native);
  		}
  
  		[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
  		static extern IntPtr g_variant_new_tuple (IntPtr[] children, UIntPtr n_children);
  
  		public static Variant NewTuple (Variant[] children)
  		{
  			if (children == null)
  				return new Variant (g_variant_new_tuple (null, new UIntPtr (0ul)));
  
  			IntPtr[] native = new IntPtr[children.Length];
  			for (int i = 0; i < children.Length; i++)
  				native[i] = children[i].Handle;
  
  			return new Variant (g_variant_new_tuple (native, new UIntPtr ((ulong) children.Length)));
  		}
  
  		[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
  		static extern IntPtr g_variant_new_array (IntPtr child_type, IntPtr[] children, UIntPtr n_children);
  
  		public static Variant NewArray (Variant[] children)
  		{
  			if (children == null) {
  				throw new ArgumentNullException ("children", "To create an empty array use NewArray (VariantType.<Type>, null)");
  			}
  
  			return NewArray (null, children);
  		}
  
  		public static Variant NewArray (VariantType type, Variant[] children)
  		{
  			if (children == null) {
  				if (type == null) {
  					throw new ArgumentException ("The type and children parameters cannot be both null");
  				} else {
  					return new Variant (g_variant_new_array (type.Handle, null, new UIntPtr (0ul)));
  				}
  			}
  
  			IntPtr[] native = new IntPtr[children.Length];
  			for (int i = 0; i < children.Length; i++)
  				native[i] = children[i].Handle;
  
  			return new Variant (g_variant_new_array (type == null ? (IntPtr) null : type.Handle,
  			                                         native, new UIntPtr ((ulong) children.Length)));
  		}
  
  		[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
  		static extern IntPtr g_variant_new_dict_entry (IntPtr k, IntPtr v);
  
  		public static Variant NewDictEntry (Variant k, Variant v)
  		{
  			return new Variant (g_variant_new_dict_entry (k.Handle, v.Handle));
  		}
  
  		public Variant (IDictionary<string, Variant> dict)
  		{
  			VariantType type = VariantType.NewDictionaryEntry (
  				VariantType.String,
  				VariantType.Variant);
  
  
gt: 			var pairs = new List<Variant> ();