summaryrefslogtreecommitdiff
path: root/gstreamer-sharp/glib-sharp/Marshaller.cs
diff options
context:
space:
mode:
Diffstat (limited to 'gstreamer-sharp/glib-sharp/Marshaller.cs')
-rw-r--r--gstreamer-sharp/glib-sharp/Marshaller.cs413
1 files changed, 413 insertions, 0 deletions
diff --git a/gstreamer-sharp/glib-sharp/Marshaller.cs b/gstreamer-sharp/glib-sharp/Marshaller.cs
new file mode 100644
index 0000000..520c9a3
--- /dev/null
+++ b/gstreamer-sharp/glib-sharp/Marshaller.cs
@@ -0,0 +1,413 @@
+// GLibSharp.Marshaller.cs : Marshalling utils
+//
+// Author: Rachel Hestilow <rachel@nullenvoid.com>
+// Mike Kestner <mkestner@ximian.com>
+//
+// Copyright (c) 2002, 2003 Rachel Hestilow
+// Copyright (c) 2004 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.
+
+
+namespace GLib {
+ using System;
+ using System.Runtime.InteropServices;
+
+ public class Marshaller {
+
+ private Marshaller () {}
+
+ [DllImport("libglib-2.0-0.dll")]
+ static extern void g_free (IntPtr mem);
+
+ public static void Free (IntPtr ptr)
+ {
+ g_free (ptr);
+ }
+
+ public static void Free (IntPtr[] ptrs)
+ {
+ if (ptrs == null)
+ return;
+
+ for (int i = 0; i < ptrs.Length; i++)
+ g_free (ptrs [i]);
+ }
+
+ [DllImport("libglib-2.0-0.dll")]
+ static extern IntPtr g_filename_to_utf8 (IntPtr mem, int len, IntPtr read, out IntPtr written, out IntPtr error);
+
+ public static string FilenamePtrToString (IntPtr ptr)
+ {
+ if (ptr == IntPtr.Zero) return null;
+
+ IntPtr dummy, error;
+ IntPtr utf8 = g_filename_to_utf8 (ptr, -1, IntPtr.Zero, out dummy, out error);
+ if (error != IntPtr.Zero)
+ throw new GLib.GException (error);
+ return Utf8PtrToString (utf8);
+ }
+
+ public static string FilenamePtrToStringGFree (IntPtr ptr)
+ {
+ string ret = FilenamePtrToString (ptr);
+ g_free (ptr);
+ return ret;
+ }
+
+ static unsafe ulong strlen (IntPtr s)
+ {
+ ulong cnt = 0;
+ byte *b = (byte *)s;
+ while (*b != 0) {
+ b++;
+ cnt++;
+ }
+ return cnt;
+ }
+
+ public static string Utf8PtrToString (IntPtr ptr)
+ {
+ if (ptr == IntPtr.Zero)
+ return null;
+
+ int len = (int) (uint) strlen (ptr);
+ byte[] bytes = new byte [len];
+ Marshal.Copy (ptr, bytes, 0, len);
+ return System.Text.Encoding.UTF8.GetString (bytes);
+ }
+
+ public static string[] Utf8PtrToString (IntPtr[] ptrs) {
+ // The last pointer is a null terminator.
+ string[] ret = new string[ptrs.Length - 1];
+ for (int i = 0; i < ret.Length; i++)
+ ret[i] = Utf8PtrToString (ptrs[i]);
+ return ret;
+ }
+
+ public static string PtrToStringGFree (IntPtr ptr)
+ {
+ string ret = Utf8PtrToString (ptr);
+ g_free (ptr);
+ return ret;
+ }
+
+ public static string[] PtrToStringGFree (IntPtr[] ptrs) {
+ // The last pointer is a null terminator.
+ string[] ret = new string[ptrs.Length - 1];
+ for (int i = 0; i < ret.Length; i++) {
+ ret[i] = Utf8PtrToString (ptrs[i]);
+ g_free (ptrs[i]);
+ }
+ return ret;
+ }
+
+ [DllImport("libglib-2.0-0.dll")]
+ static extern IntPtr g_filename_from_utf8 (IntPtr mem, int len, IntPtr read, out IntPtr written, out IntPtr error);
+
+ public static IntPtr StringToFilenamePtr (string str)
+ {
+ if (str == null)
+ return IntPtr.Zero;
+
+ IntPtr dummy, error;
+ IntPtr utf8 = StringToPtrGStrdup (str);
+ IntPtr result = g_filename_from_utf8 (utf8, -1, IntPtr.Zero, out dummy, out error);
+ g_free (utf8);
+ if (error != IntPtr.Zero)
+ throw new GException (error);
+
+ return result;
+ }
+
+ public static IntPtr StringToPtrGStrdup (string str) {
+ if (str == null)
+ return IntPtr.Zero;
+ byte[] bytes = System.Text.Encoding.UTF8.GetBytes (str);
+ IntPtr result = g_malloc (new UIntPtr ((ulong)bytes.Length + 1));
+ Marshal.Copy (bytes, 0, result, bytes.Length);
+ Marshal.WriteByte (result, bytes.Length, 0);
+ return result;
+ }
+
+ public static string StringFormat (string format, params object[] args) {
+ string ret = String.Format (format, args);
+ if (ret.IndexOf ('%') == -1)
+ return ret;
+ else
+ return ret.Replace ("%", "%%");
+ }
+
+ public static IntPtr[] StringArrayToNullTermPointer (string[] strs)
+ {
+ if (strs == null)
+ return null;
+ IntPtr[] result = new IntPtr [strs.Length + 1];
+ for (int i = 0; i < strs.Length; i++)
+ result [i] = StringToPtrGStrdup (strs [i]);
+ result [strs.Length] = IntPtr.Zero;
+ return result;
+ }
+
+ [DllImport("libglib-2.0-0.dll")]
+ static extern void g_strfreev (IntPtr mem);
+
+ public static void StrFreeV (IntPtr null_term_array)
+ {
+ g_strfreev (null_term_array);
+ }
+
+ public static string[] NullTermPtrToStringArray (IntPtr null_term_array, bool owned)
+ {
+ if (null_term_array == IntPtr.Zero)
+ return new string [0];
+
+ int count = 0;
+ System.Collections.ArrayList result = new System.Collections.ArrayList ();
+ IntPtr s = Marshal.ReadIntPtr (null_term_array, count++ * IntPtr.Size);
+ while (s != IntPtr.Zero) {
+ result.Add (Utf8PtrToString (s));
+ s = Marshal.ReadIntPtr (null_term_array, count++ * IntPtr.Size);
+ }
+
+ if (owned)
+ g_strfreev (null_term_array);
+
+ return (string[]) result.ToArray (typeof(string));
+ }
+
+ public static string[] PtrToStringArrayGFree (IntPtr string_array)
+ {
+ if (string_array == IntPtr.Zero)
+ return new string [0];
+
+ int count = 0;
+ while (Marshal.ReadIntPtr (string_array, count*IntPtr.Size) != IntPtr.Zero)
+ ++count;
+
+ string[] members = new string[count];
+ for (int i = 0; i < count; ++i) {
+ IntPtr s = Marshal.ReadIntPtr (string_array, i * IntPtr.Size);
+ members[i] = GLib.Marshaller.PtrToStringGFree (s);
+ }
+ GLib.Marshaller.Free (string_array);
+ return members;
+ }
+
+ // Argv marshalling -- unpleasantly complex, but
+ // don't know of a better way to do it.
+ //
+ // Currently, the 64-bit cleanliness is
+ // hypothetical. It's also ugly, but I don't know of a
+ // construct to handle both 32 and 64 bitness
+ // transparently, since we need to alloc buffers of
+ // [native pointer size] * [count] bytes.
+
+ [DllImport("libglib-2.0-0.dll")]
+ static extern IntPtr g_malloc(UIntPtr size);
+
+ public static IntPtr Malloc (ulong size)
+ {
+ return g_malloc (new UIntPtr (size));
+ }
+
+ static bool check_sixtyfour () {
+ int szint = Marshal.SizeOf (typeof (int));
+ int szlong = Marshal.SizeOf (typeof (long));
+ int szptr = IntPtr.Size;
+
+ if (szptr == szint)
+ return false;
+ if (szptr == szlong)
+ return true;
+
+ throw new Exception ("Pointers are neither int- nor long-sized???");
+ }
+
+ static IntPtr make_buf_32 (string[] args)
+ {
+ int[] ptrs = new int[args.Length];
+
+ for (int i = 0; i < args.Length; i++)
+ ptrs[i] = (int) Marshal.StringToHGlobalAuto (args[i]);
+
+ IntPtr buf = g_malloc (new UIntPtr ((ulong) Marshal.SizeOf(typeof(int)) *
+ (ulong) args.Length));
+ Marshal.Copy (ptrs, 0, buf, ptrs.Length);
+ return buf;
+ }
+
+ static IntPtr make_buf_64 (string[] args)
+ {
+ long[] ptrs = new long[args.Length];
+
+ for (int i = 0; i < args.Length; i++)
+ ptrs[i] = (long) Marshal.StringToHGlobalAuto (args[i]);
+
+ IntPtr buf = g_malloc (new UIntPtr ((ulong) Marshal.SizeOf(typeof(long)) *
+ (ulong) args.Length));
+ Marshal.Copy (ptrs, 0, buf, ptrs.Length);
+ return buf;
+ }
+
+ [Obsolete ("Use GLib.Argv instead to avoid leaks.")]
+ public static IntPtr ArgvToArrayPtr (string[] args)
+ {
+ if (args.Length == 0)
+ return IntPtr.Zero;
+
+ if (check_sixtyfour ())
+ return make_buf_64 (args);
+
+ return make_buf_32 (args);
+ }
+
+ // should we be freeing these pointers? they're marshalled
+ // from our own strings, so I think not ...
+
+ static string[] unmarshal_32 (IntPtr buf, int argc)
+ {
+ int[] ptrs = new int[argc];
+ string[] args = new string[argc];
+
+ Marshal.Copy (buf, ptrs, 0, argc);
+
+ for (int i = 0; i < ptrs.Length; i++)
+ args[i] = Marshal.PtrToStringAuto ((IntPtr) ptrs[i]);
+
+ return args;
+ }
+
+ static string[] unmarshal_64 (IntPtr buf, int argc)
+ {
+ long[] ptrs = new long[argc];
+ string[] args = new string[argc];
+
+ Marshal.Copy (buf, ptrs, 0, argc);
+
+ for (int i = 0; i < ptrs.Length; i++)
+ args[i] = Marshal.PtrToStringAuto ((IntPtr) ptrs[i]);
+
+ return args;
+ }
+
+ [Obsolete ("Use GLib.Argv instead to avoid leaks.")]
+ public static string[] ArrayPtrToArgv (IntPtr array, int argc)
+ {
+ if (argc == 0)
+ return new string[0];
+
+ if (check_sixtyfour ())
+ return unmarshal_64 (array, argc);
+
+ return unmarshal_32 (array, argc);
+ }
+
+ static DateTime local_epoch = new DateTime (1970, 1, 1, 0, 0, 0);
+ static int utc_offset = (int) (TimeZone.CurrentTimeZone.GetUtcOffset (DateTime.Now)).TotalSeconds;
+
+ public static IntPtr DateTimeTotime_t (DateTime time)
+ {
+ return new IntPtr (((long)time.Subtract (local_epoch).TotalSeconds) - utc_offset);
+ }
+
+ public static DateTime time_tToDateTime (IntPtr time_t)
+ {
+ return local_epoch.AddSeconds (time_t.ToInt64 () + utc_offset);
+ }
+
+ [DllImport("libglib-2.0-0.dll")]
+ static extern IntPtr g_malloc0 (UIntPtr size);
+
+ [DllImport("libglib-2.0-0.dll")]
+ static extern int g_unichar_to_utf8 (uint c, IntPtr buf);
+
+ public static char GUnicharToChar (uint ucs4_char)
+ {
+ if (ucs4_char == 0)
+ return (char) 0;
+
+ string ret = GUnicharToString (ucs4_char);
+ if (ret.Length != 1)
+ throw new ArgumentOutOfRangeException ("ucs4char is not representable by a char.");
+
+ return ret [0];
+ }
+
+ public static string GUnicharToString (uint ucs4_char)
+ {
+ if (ucs4_char == 0)
+ return String.Empty;
+
+ IntPtr buf = g_malloc0 (new UIntPtr (7));
+ g_unichar_to_utf8 (ucs4_char, buf);
+ return PtrToStringGFree (buf);
+ }
+
+ [DllImport("libglib-2.0-0.dll")]
+ static extern IntPtr g_utf16_to_ucs4 (ref ushort c, IntPtr len, IntPtr d1, IntPtr d2, IntPtr d3);
+
+ public static uint CharToGUnichar (char c)
+ {
+ ushort val = (ushort) c;
+ IntPtr ucs4_str = g_utf16_to_ucs4 (ref val, new IntPtr (1), IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
+ uint result = (uint) Marshal.ReadInt32 (ucs4_str);
+ g_free (ucs4_str);
+ return result;
+ }
+
+ public static IntPtr StructureToPtrAlloc (object o)
+ {
+ IntPtr result = Marshal.AllocHGlobal (Marshal.SizeOf (o));
+ Marshal.StructureToPtr (o, result, false);
+ return result;
+ }
+
+ public static Array ListPtrToArray (IntPtr list_ptr, Type list_type, bool owned, bool elements_owned, Type elem_type)
+ {
+ Type array_type = elem_type == typeof (ListBase.FilenameString) ? typeof (string) : elem_type;
+ ListBase list;
+ if (list_type == typeof(GLib.List))
+ list = new GLib.List (list_ptr, elem_type, owned, elements_owned);
+ else
+ list = new GLib.SList (list_ptr, elem_type, owned, elements_owned);
+
+ using (list)
+ return ListToArray (list, array_type);
+ }
+
+ public static Array PtrArrayToArray (IntPtr list_ptr, bool owned, bool elements_owned, Type elem_type)
+ {
+ GLib.PtrArray array = new GLib.PtrArray (list_ptr, elem_type, owned, elements_owned);
+ Array ret = Array.CreateInstance (elem_type, array.Count);
+ array.CopyTo (ret, 0);
+ array.Dispose ();
+ return ret;
+ }
+
+ public static Array ListToArray (ListBase list, System.Type type)
+ {
+ Array result = Array.CreateInstance (type, list.Count);
+ if (list.Count > 0)
+ list.CopyTo (result, 0);
+
+ if (type.IsSubclassOf (typeof (GLib.Opaque)))
+ list.elements_owned = false;
+
+ return result;
+ }
+ }
+}
+