// SList.cs - GSList class wrapper implementation // // Authors: Mike Kestner // // (c) 2002 Mike Kestner namespace GLib { using System; using System.Collections; using System.Runtime.InteropServices; /// /// ListBase Class /// /// /// /// Base class for GList and GSList. /// public abstract class ListBase : IDisposable, ICollection, GLib.IWrapper, ICloneable { private IntPtr list_ptr = IntPtr.Zero; private int length = -1; private bool managed = false; protected Type element_type = null; abstract internal IntPtr GetData (IntPtr current); abstract internal IntPtr Next (IntPtr current); 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); private ListBase () { } internal ListBase (IntPtr list, Type element_type) { list_ptr = list; this.element_type = element_type; } internal ListBase (IntPtr list) { list_ptr = list; } ~ListBase () { Console.WriteLine ("entering dispose"); Dispose (); Console.WriteLine ("leaving dispose"); } public bool Managed { set { managed = value; } } /// /// Handle Property /// /// /// /// A raw list reference for marshaling situations. /// public IntPtr Handle { get { return list_ptr; } } internal IntPtr Raw { get { return list_ptr; } set { if (managed && list_ptr != IntPtr.Zero) Dispose (); list_ptr = value; } } public void Append (IntPtr raw) { list_ptr = Append (list_ptr, raw); } 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; } } // 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); } 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; if (list.element_type != null) { if (list.element_type == typeof (string)) ret = Marshal.PtrToStringAnsi (data); else if (list.element_type == typeof (int)) ret = (int) data; else if (list.element_type.IsValueType) ret = Marshal.PtrToStructure (data, list.element_type); else ret = Activator.CreateInstance (list.element_type, new object[] {data}); } else if (Object.IsObject (data)) ret = GLib.Object.GetObject (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 () { if (!managed) return; if (list_ptr != IntPtr.Zero) Free (list_ptr); list_ptr = IntPtr.Zero; length = -1; } // ICloneable abstract public object Clone (); } }