// GLib.Value.cs - GLib Value class implementation // // Author: Mike Kestner // // (c) 2001 Mike Kestner, (c) 2003 Novell, Inc. namespace GLib { using System; using System.Collections; using System.Runtime.InteropServices; using GLibSharp; /// /// Value Class /// /// /// /// An arbitrary data type similar to a CORBA Any which is used /// to get and set properties on Objects. /// public class Value : IDisposable { IntPtr _val; bool needs_dispose = true; // Destructor is required since we are allocating unmanaged // heap resources. [DllImport("libglib-2.0-0.dll")] static extern void g_free (IntPtr mem); [DllImport("libgobject-2.0-0.dll")] static extern void g_value_unset (IntPtr mem); ~Value () { Dispose (); } static bool idle_queued; static Queue idle_queue = new Queue (); static bool DoDispose () { IntPtr [] vals; lock (idle_queue){ vals = new IntPtr [idle_queue.Count]; idle_queue.CopyTo (vals, 0); idle_queue.Clear (); } lock (typeof (Value)) idle_queued = false; foreach (IntPtr v in vals) { if (v == IntPtr.Zero) continue; g_value_unset (v); g_free (v); } return false; } public void Dispose () { if (_val != IntPtr.Zero && needs_dispose) { lock (idle_queue) { idle_queue.Enqueue (_val); lock (typeof (Value)){ if (!idle_queued) { Idle.Add (new IdleHandler (DoDispose)); idle_queued = true; } } } _val = IntPtr.Zero; } if (buf != IntPtr.Zero) { Marshal.FreeHGlobal (buf); buf = IntPtr.Zero; } } // import the glue function to allocate values on heap [DllImport("glibsharpglue")] static extern IntPtr gtksharp_value_create(IntPtr type); [DllImport("glibsharpglue")] static extern IntPtr gtksharp_value_create_from_property(IntPtr obj, string name); // Constructor to wrap a raw GValue ref. We need the dummy param // to distinguish this ctor from the TypePointer ctor. public Value (IntPtr val, IntPtr dummy) { _val = val; needs_dispose = false; } /// /// Value Constructor /// /// /// /// Constructs a new empty value that can be used /// to receive "out" GValue parameters. /// public Value () { _val = gtksharp_value_create (GType.Invalid.Val); } /// /// Value Constructor /// /// /// /// Constructs a new empty initialized value that can be used /// to receive "out" GValue parameters. /// public Value (GLib.GType gtype) { _val = gtksharp_value_create (gtype.Val); } /// /// Value Constructor /// /// /// /// Constructs a Value corresponding to the type of the /// specified property. /// public Value (IntPtr obj, string prop_name) { _val = gtksharp_value_create_from_property (obj, prop_name); } [DllImport("libgobject-2.0-0.dll")] static extern void g_value_set_boolean (IntPtr val, bool data); /// /// Value Constructor /// /// /// /// Constructs a Value from a specified boolean. /// public Value (bool val) { _val = gtksharp_value_create(GType.Boolean.Val); g_value_set_boolean (_val, val); } [DllImport("libgobject-2.0-0.dll")] static extern void g_value_set_boxed (IntPtr val, IntPtr data); /* /// /// Value Constructor /// /// /// /// Constructs a Value from a specified boxed type. /// public Value (GLib.Boxed val) { _val = gtksharp_value_create(GType.Boxed); //g_value_set_boxed (_val, val.Handle); } public Value (IntPtr obj, string prop_name, Boxed val) { _val = gtksharp_value_create_from_property (obj, prop_name); //g_value_set_boxed (_val, val.Handle); } */ public Value (IntPtr obj, string prop_name, Opaque val) { _val = gtksharp_value_create_from_property (obj, prop_name); g_value_set_boxed (_val, val.Handle); } [DllImport("libgobject-2.0-0.dll")] static extern void g_value_set_double (IntPtr val, double data); /// /// Value Constructor /// /// /// /// Constructs a Value from a specified double. /// public Value (double val) { _val = gtksharp_value_create (GType.Double.Val); g_value_set_double (_val, val); } [DllImport("libgobject-2.0-0.dll")] static extern void g_value_set_float (IntPtr val, float data); /// /// Value Constructor /// /// /// /// Constructs a Value from a specified float. /// public Value (float val) { _val = gtksharp_value_create (GType.Float.Val); g_value_set_float (_val, val); } [DllImport("libgobject-2.0-0.dll")] static extern void g_value_set_int (IntPtr val, int data); /// /// Value Constructor /// /// /// /// Constructs a Value from a specified integer. /// public Value (int val) { _val = gtksharp_value_create (GType.Int.Val); g_value_set_int (_val, val); } [DllImport("libgobject-2.0-0.dll")] static extern void g_value_set_object (IntPtr val, IntPtr data); /// /// Value Constructor /// /// /// /// Constructs a Value from a specified object. /// public Value (GLib.Object val) { _val = gtksharp_value_create (val.GetGType ().Val); g_value_set_object (_val, val.Handle); } [DllImport("libgobject-2.0-0.dll")] static extern void g_value_set_pointer (IntPtr val, IntPtr data); /// /// Value Constructor /// /// /// /// Constructs a Value from a specified pointer. /// public Value (IntPtr val) { _val = gtksharp_value_create (GType.Pointer.Val); g_value_set_pointer (_val, val); } [DllImport("libgobject-2.0-0.dll")] static extern void g_value_set_string (IntPtr val, string data); /// /// Value Constructor /// /// /// /// Constructs a Value from a specified string. /// public Value (string val) { _val = gtksharp_value_create (GType.String.Val); g_value_set_string (_val, val); } [DllImport("libgobject-2.0-0.dll")] static extern void g_value_set_uint (IntPtr val, uint data); /// /// Value Constructor /// /// /// /// Constructs a Value from a specified uint. /// public Value (uint val) { _val = gtksharp_value_create (GType.UInt.Val); g_value_set_uint (_val, val); } /// /// Value Constructor /// /// /// /// Constructs a Value from a specified ushort. /// public Value (ushort val) { _val = gtksharp_value_create (GType.UInt.Val); g_value_set_uint (_val, val); } [DllImport("libgobject-2.0-0.dll")] static extern void g_value_set_enum (IntPtr val, int data); [DllImport("libgobject-2.0-0.dll")] static extern void g_value_set_flags (IntPtr val, uint data); [DllImport("libgobject-2.0-0.dll")] static extern void g_value_set_char (IntPtr val, char data); /// /// Value Constructor /// /// /// /// Constructs a Value from a specified enum wrapper. /// public Value (IntPtr obj, string prop_name, EnumWrapper wrap) { _val = gtksharp_value_create_from_property (obj, prop_name); if (wrap.flags) g_value_set_flags (_val, (uint) (int) wrap); else g_value_set_enum (_val, (int) wrap); } [DllImport("libgobject-2.0-0.dll")] static extern bool g_type_is_a (IntPtr type, IntPtr is_a_type); IntPtr buf = IntPtr.Zero; /// /// Value Constructor /// /// /// /// Constructs a Value from any object, including a managed /// type. /// public Value (object obj) { GType type = TypeConverter.LookupType (obj.GetType ()); if (type == GType.None) { _val = gtksharp_value_create (ManagedValue.GType.Val); } else if (type == GType.Object) { _val = gtksharp_value_create (((GLib.Object) obj).GetGType ().Val); } else { _val = gtksharp_value_create (type.Val); } if (type == GType.None) g_value_set_boxed (_val, ManagedValue.WrapObject (obj)); else if (type == GType.String) g_value_set_string (_val, (string) obj); else if (type == GType.Boolean) g_value_set_boolean (_val, (bool) obj); else if (type == GType.Int) g_value_set_int (_val, (int) obj); else if (type == GType.Double) g_value_set_double (_val, (double) obj); else if (type == GType.Float) g_value_set_float (_val, (float) obj); else if (type == GType.Char) g_value_set_char (_val, (char) obj); else if (type == GType.UInt) g_value_set_uint (_val, (uint) obj); else if (type == GType.Object) g_value_set_object (_val, ((GLib.Object) obj).Handle); else if (type == GType.Pointer) { if (obj is IWrapper) { g_value_set_pointer (_val, ((IWrapper)obj).Handle); return; } buf = Marshal.AllocHGlobal (Marshal.SizeOf (obj.GetType())); Marshal.StructureToPtr (obj, buf, false); g_value_set_pointer (_val, buf); } else if (g_type_is_a (type.Val, GLib.GType.Boxed.Val)) { if (obj is IWrapper) { g_value_set_boxed (_val, ((IWrapper)obj).Handle); return; } buf = Marshal.AllocHGlobal (Marshal.SizeOf (obj.GetType())); Marshal.StructureToPtr (obj, buf, false); g_value_set_boxed (_val, buf); } else throw new Exception ("Unknown type"); } [DllImport("libgobject-2.0-0.dll")] static extern bool g_value_get_boolean (IntPtr val); /// /// Value to Boolean Conversion /// /// /// /// Extracts a bool from a Value. Note, this method /// will produce an exception if the Value does not hold a /// boolean value. /// public static explicit operator bool (Value val) { // FIXME: Insert an appropriate exception here if // _val.type indicates an error. return g_value_get_boolean (val._val); } [DllImport("libgobject-2.0-0.dll")] static extern IntPtr g_value_get_boxed (IntPtr val); public static explicit operator GLib.Opaque (Value val) { return GLib.Opaque.GetOpaque (g_value_get_boxed (val._val)); } /// /// Value to Boxed Conversion /// /// /// /// Extracts a boxed type from a Value. Note, this method /// will produce an exception if the Value does not hold a /// boxed type value. /// public static explicit operator GLib.Boxed (Value val) { return new GLib.Boxed (g_value_get_boxed (val._val)); } [DllImport("libgobject-2.0-0.dll")] static extern double g_value_get_double (IntPtr val); /// /// Value to Double Conversion /// /// /// /// Extracts a double from a Value. Note, this method /// will produce an exception if the Value does not hold a /// double value. /// public static explicit operator double (Value val) { // FIXME: Insert an appropriate exception here if // _val.type indicates an error. return g_value_get_double (val._val); } [DllImport("libgobject-2.0-0.dll")] static extern float g_value_get_float (IntPtr val); /// /// Value to Float Conversion /// /// /// /// Extracts a float from a Value. Note, this method /// will produce an exception if the Value does not hold a /// float value. /// public static explicit operator float (Value val) { // FIXME: Insert an appropriate exception here if // _val.type indicates an error. return g_value_get_float (val._val); } [DllImport("libgobject-2.0-0.dll")] static extern int g_value_get_int (IntPtr val); /// /// Value to Integer Conversion /// /// /// /// Extracts an int from a Value. Note, this method /// will produce an exception if the Value does not hold a /// integer value. /// public static explicit operator int (Value val) { // FIXME: Insert an appropriate exception here if // _val.type indicates an error. return g_value_get_int (val._val); } [DllImport("libgobject-2.0-0.dll")] static extern IntPtr g_value_get_object (IntPtr val); /// /// Value to Object Conversion /// /// /// /// Extracts an object from a Value. Note, this method /// will produce an exception if the Value does not hold a /// object value. /// public static explicit operator GLib.Object (Value val) { // FIXME: Insert an appropriate exception here if // _val.type indicates an error. return GLib.Object.GetObject(g_value_get_object (val._val), true); } /// /// Value to Unresolved Object Conversion /// /// /// /// Extracts an object from a Value without looking up its wrapping /// class. /// Note, this method will produce an exception if the Value does /// not hold a object value. /// public static explicit operator GLib.UnwrappedObject (Value val) { // FIXME: Insert an appropriate exception here if // _val.type indicates an error. return new UnwrappedObject(g_value_get_object (val._val)); } [DllImport("libgobject-2.0-0.dll")] static extern IntPtr g_value_get_pointer (IntPtr val); /// /// Value to Pointer Conversion /// /// /// /// Extracts a pointer from a Value. Note, this method /// will produce an exception if the Value does not hold a /// pointer value. /// public static explicit operator IntPtr (Value val) { // FIXME: Insert an appropriate exception here if // _val.type indicates an error. return g_value_get_pointer (val._val); } [DllImport("libgobject-2.0-0.dll")] static extern IntPtr g_value_get_string (IntPtr val); /// /// Value to String Conversion /// /// /// /// Extracts a string from a Value. Note, this method /// will produce an exception if the Value does not hold a /// string value. /// public static explicit operator String (Value val) { // FIXME: Insert an appropriate exception here if // _val.type indicates an error. IntPtr str = g_value_get_string (val._val); return str == IntPtr.Zero ? null : Marshal.PtrToStringAnsi (str); } [DllImport("libgobject-2.0-0.dll")] static extern uint g_value_get_uint (IntPtr val); /// /// Value to Unsigned Integer Conversion /// /// /// /// Extracts an uint from a Value. Note, this method /// will produce an exception if the Value does not hold a /// unsigned integer value. /// public static explicit operator uint (Value val) { // FIXME: Insert an appropriate exception here if // _val.type indicates an error. return g_value_get_uint (val._val); } /// /// Value to Unsigned Short Conversion /// /// /// /// Extracts a ushort from a Value. Note, this method /// will produce an exception if the Value does not hold a /// unsigned integer value. /// public static explicit operator ushort (Value val) { // FIXME: Insert an appropriate exception here if // _val.type indicates an error. return (ushort) g_value_get_uint (val._val); } [DllImport("libgobject-2.0-0.dll")] static extern int g_value_get_enum (IntPtr val); [DllImport("libgobject-2.0-0.dll")] static extern uint g_value_get_flags (IntPtr val); /// /// Value to Enum Conversion /// /// /// /// Extracts an enum from a Value. Note, this method /// will produce an exception if the Value does not hold an /// enum value. /// public static explicit operator EnumWrapper (Value val) { // FIXME: Insert an appropriate exception here if // _val.type indicates an error. // FIXME: handle flags return new EnumWrapper (g_value_get_enum (val._val), false); } [DllImport("glibsharpglue")] static extern IntPtr gtksharp_value_get_value_type (IntPtr val); public object Val { get { GLib.GType type = new GLib.GType (gtksharp_value_get_value_type (_val)); if (type == ManagedValue.GType) { return ManagedValue.ObjectForWrapper (g_value_get_boxed (_val)); } if (type == GType.String) return (string) this; else if (type == GType.Boolean) return (bool) this; else if (type == GType.Int) return (int) this; else if (type == GType.Double) return (double) this; else if (type == GType.Float) return (float) this; else if (type == GType.Char) return (char) this; else if (type == GType.UInt) return (uint) this; else if (type == GType.Object) return (GLib.Object) this; else throw new Exception ("Unknown type"); } set { GType type = GLibSharp.TypeConverter.LookupType (value.GetType()); if (type == GType.None) g_value_set_boxed (_val, ManagedValue.WrapObject (value)); else if (type == GType.String) g_value_set_string (_val, (string) value); else if (type == GType.Boolean) g_value_set_boolean (_val, (bool) value); else if (type == GType.Int) g_value_set_int (_val, (int) value); else if (type == GType.Double) g_value_set_double (_val, (double) value); else if (type == GType.Float) g_value_set_float (_val, (float) value); else if (type == GType.Char) g_value_set_char (_val, (char) value); else if (type == GType.UInt) g_value_set_uint (_val, (uint) value); else if (type == GType.Object) g_value_set_object (_val, ((GLib.Object) value).Handle); else throw new Exception ("Unknown type"); } } /// /// Handle Property /// /// /// /// Read only. Accesses a pointer to the raw GValue. /// public IntPtr Handle { get { return _val; } } } }