summaryrefslogtreecommitdiff
path: root/gstreamer-sharp/glib-sharp/ListBase.cs
diff options
context:
space:
mode:
Diffstat (limited to 'gstreamer-sharp/glib-sharp/ListBase.cs')
-rw-r--r--gstreamer-sharp/glib-sharp/ListBase.cs279
1 files changed, 279 insertions, 0 deletions
diff --git a/gstreamer-sharp/glib-sharp/ListBase.cs b/gstreamer-sharp/glib-sharp/ListBase.cs
new file mode 100644
index 0000000..7cc0fe4
--- /dev/null
+++ b/gstreamer-sharp/glib-sharp/ListBase.cs
@@ -0,0 +1,279 @@
+// ListBase.cs - List base class implementation
+//
+// Authors: Mike Kestner <mkestner@novell.com>
+//
+// Copyright (c) 2002 Mike Kestner
+// Copyright (c) 2005 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.Collections;
+ using System.Runtime.InteropServices;
+
+ public abstract class ListBase : IDisposable, ICollection, GLib.IWrapper, ICloneable {
+
+ private IntPtr list_ptr = IntPtr.Zero;
+ private int length = -1;
+ private bool managed = false;
+ internal bool elements_owned = false;
+ protected System.Type element_type = null;
+
+ abstract internal IntPtr NthData (uint index);
+ abstract internal int Length (IntPtr list);
+ abstract internal void Free (IntPtr list);
+ abstract internal IntPtr Append (IntPtr current, IntPtr raw);
+ abstract internal IntPtr Prepend (IntPtr current, IntPtr raw);
+
+ internal ListBase (IntPtr list, System.Type element_type, bool owned, bool elements_owned)
+ {
+ list_ptr = list;
+ this.element_type = element_type;
+ managed = owned;
+ this.elements_owned = elements_owned;
+ }
+
+ ~ListBase ()
+ {
+ Dispose (false);
+ }
+
+ [Obsolete ("Replaced by owned parameter on ctor.")]
+ public bool Managed {
+ set { managed = value; }
+ }
+
+ public IntPtr Handle {
+ get {
+ return list_ptr;
+ }
+ }
+
+ public void Append (IntPtr raw)
+ {
+ list_ptr = Append (list_ptr, raw);
+ }
+
+ public void Append (string item)
+ {
+ this.Append (Marshaller.StringToPtrGStrdup (item));
+ }
+
+ public void Append (object item)
+ {
+ this.Append (AllocNativeElement (item));
+ }
+
+ public void Prepend (IntPtr raw)
+ {
+ list_ptr = Prepend (list_ptr, raw);
+ }
+
+ // ICollection
+ public int Count {
+ get {
+ if (length == -1)
+ length = Length (list_ptr);
+ return length;
+ }
+ }
+
+ public object this [int index] {
+ get {
+ IntPtr data = NthData ((uint) index);
+ object ret = null;
+ ret = DataMarshal (data);
+ return ret;
+ }
+ }
+
+ // Synchronization could be tricky here. Hmm.
+ public bool IsSynchronized {
+ get { return false; }
+ }
+
+ public object SyncRoot {
+ get { return null; }
+ }
+
+ public void CopyTo (Array array, int index)
+ {
+ object[] orig = new object[Count];
+ int i = 0;
+ foreach (object o in this)
+ orig [i++] = o;
+
+ orig.CopyTo (array, index);
+ }
+
+ public class FilenameString {
+ private FilenameString () {}
+ }
+
+ IntPtr AllocNativeElement (object element)
+ {
+ if (element_type == null) {
+ if (element is IWrapper)
+ return (element as IWrapper).Handle;
+ else
+ return (IntPtr) GCHandle.Alloc (element);
+ } else {
+ if (element_type == typeof (string))
+ return Marshaller.StringToPtrGStrdup (element as string);
+ else if (element_type == typeof (FilenameString))
+ return Marshaller.StringToFilenamePtr (element as string);
+ else if (element_type == typeof (IntPtr))
+ return (IntPtr) GCHandle.Alloc (element);
+ else if (typeof (IWrapper).IsAssignableFrom (element_type))
+ return (element as IWrapper).Handle;
+ else if (element_type == typeof (int))
+ return new IntPtr ((int) element);
+ else if (element_type.IsValueType)
+ return Marshaller.StructureToPtrAlloc (element);
+ }
+ return IntPtr.Zero;
+ }
+
+ internal object DataMarshal (IntPtr data)
+ {
+ object ret = null;
+ if (element_type != null) {
+ if (element_type == typeof (string))
+ ret = Marshaller.Utf8PtrToString (data);
+ else if (element_type == typeof (FilenameString))
+ ret = Marshaller.FilenamePtrToString (data);
+ else if (element_type == typeof (IntPtr))
+ ret = data;
+ else if (element_type.IsSubclassOf (typeof (GLib.Object)))
+ ret = GLib.Object.GetObject (data, false);
+ else if (element_type.IsSubclassOf (typeof (GLib.Opaque)))
+ ret = GLib.Opaque.GetOpaque (data, element_type, elements_owned);
+ else if (element_type == typeof (int))
+ ret = (int) data;
+ else if (element_type.IsValueType)
+ ret = Marshal.PtrToStructure (data, element_type);
+ else if (element_type.IsInterface) {
+ Type adapter_type = element_type.Assembly.GetType (element_type.FullName + "Adapter");
+ System.Reflection.MethodInfo method = adapter_type.GetMethod ("GetObject", new Type[] {typeof(IntPtr), typeof(bool)});
+ ret = method.Invoke (null, new object[] {data, false});
+ } else
+ ret = Activator.CreateInstance (element_type, new object[] {data});
+
+ } else if (Object.IsObject (data))
+ ret = GLib.Object.GetObject (data, false);
+
+ return ret;
+ }
+
+ [DllImport ("libglib-2.0-0.dll")]
+ static extern void g_free (IntPtr item);
+
+ [DllImport ("libgobject-2.0-0.dll")]
+ static extern void g_object_unref (IntPtr item);
+
+ public void Empty ()
+ {
+ if (elements_owned)
+ for (uint i = 0; i < Count; i++)
+ if (typeof (GLib.Object).IsAssignableFrom (element_type))
+ g_object_unref (NthData (i));
+ else if (typeof (GLib.Opaque).IsAssignableFrom (element_type))
+ GLib.Opaque.GetOpaque (NthData (i), element_type, true).Dispose ();
+ else
+ g_free (NthData (i));
+
+ if (managed)
+ FreeList ();
+ }
+
+ IntPtr GetData (IntPtr current)
+ {
+ // data field is at offset 0 for GList and GSList
+ return Marshal.ReadIntPtr (current);
+ }
+
+ IntPtr Next (IntPtr current)
+ {
+ // next field follows gpointer data field for GList and GSList
+ return Marshal.ReadIntPtr (current, IntPtr.Size);
+ }
+
+ private class ListEnumerator : IEnumerator
+ {
+ private IntPtr current = IntPtr.Zero;
+ private ListBase list;
+
+ public ListEnumerator (ListBase list)
+ {
+ this.list = list;
+ }
+
+ public object Current {
+ get {
+ IntPtr data = list.GetData (current);
+ object ret = null;
+ ret = list.DataMarshal (data);
+ return ret;
+ }
+ }
+
+ public bool MoveNext ()
+ {
+ if (current == IntPtr.Zero)
+ current = list.list_ptr;
+ else
+ current = list.Next (current);
+ return (current != IntPtr.Zero);
+ }
+
+ public void Reset ()
+ {
+ current = IntPtr.Zero;
+ }
+ }
+
+ // IEnumerable
+ public IEnumerator GetEnumerator ()
+ {
+ return new ListEnumerator (this);
+ }
+
+ // IDisposable
+ public void Dispose ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this);
+ }
+
+ protected virtual void Dispose (bool disposing)
+ {
+ Empty ();
+ }
+
+ void FreeList ()
+ {
+ if (list_ptr != IntPtr.Zero)
+ Free (list_ptr);
+ list_ptr = IntPtr.Zero;
+ length = -1;
+ }
+
+ // ICloneable
+ abstract public object Clone ();
+ }
+}