2002-09-01 04:46:38 +00:00
|
|
|
// SList.cs - GSList class wrapper implementation
|
|
|
|
//
|
|
|
|
// Authors: Mike Kestner <mkestner@speakeasy.net>
|
|
|
|
//
|
|
|
|
// (c) 2002 Mike Kestner
|
|
|
|
|
|
|
|
namespace GLib {
|
|
|
|
|
|
|
|
using System;
|
|
|
|
using System.Collections;
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// ListBase Class
|
|
|
|
/// </summary>
|
|
|
|
///
|
|
|
|
/// <remarks>
|
|
|
|
/// Base class for GList and GSList.
|
|
|
|
/// </remarks>
|
|
|
|
|
2002-09-01 10:40:24 +00:00
|
|
|
public abstract class ListBase : IDisposable, ICollection, GLib.IWrapper, ICloneable {
|
2002-09-01 04:46:38 +00:00
|
|
|
|
|
|
|
private IntPtr list_ptr = IntPtr.Zero;
|
|
|
|
private int length = -1;
|
|
|
|
private bool managed = false;
|
2003-02-24 06:39:30 +00:00
|
|
|
protected System.Type element_type = null;
|
2002-09-01 04:46:38 +00:00
|
|
|
|
|
|
|
abstract internal IntPtr GetData (IntPtr current);
|
|
|
|
abstract internal IntPtr Next (IntPtr current);
|
|
|
|
abstract internal int Length (IntPtr list);
|
|
|
|
abstract internal void Free (IntPtr list);
|
2002-10-11 15:43:52 +00:00
|
|
|
abstract internal IntPtr Append (IntPtr current, IntPtr raw);
|
|
|
|
abstract internal IntPtr Prepend (IntPtr current, IntPtr raw);
|
2002-09-01 04:46:38 +00:00
|
|
|
|
2002-09-01 10:40:24 +00:00
|
|
|
private ListBase ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2003-02-24 06:39:30 +00:00
|
|
|
internal ListBase (IntPtr list, System.Type element_type)
|
2002-09-01 04:46:38 +00:00
|
|
|
{
|
|
|
|
list_ptr = list;
|
|
|
|
this.element_type = element_type;
|
|
|
|
}
|
|
|
|
|
2002-09-01 10:40:24 +00:00
|
|
|
internal ListBase (IntPtr list)
|
2002-09-01 04:46:38 +00:00
|
|
|
{
|
|
|
|
list_ptr = list;
|
|
|
|
}
|
|
|
|
|
|
|
|
~ListBase ()
|
|
|
|
{
|
|
|
|
Dispose ();
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool Managed {
|
|
|
|
set { managed = value; }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Handle Property
|
|
|
|
/// </summary>
|
|
|
|
///
|
|
|
|
/// <remarks>
|
|
|
|
/// A raw list reference for marshaling situations.
|
|
|
|
/// </remarks>
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-10-11 15:43:52 +00:00
|
|
|
public void Append (IntPtr raw)
|
|
|
|
{
|
|
|
|
list_ptr = Append (list_ptr, raw);
|
|
|
|
}
|
|
|
|
|
2003-08-19 21:07:24 +00:00
|
|
|
public void Append (string item)
|
|
|
|
{
|
|
|
|
this.Append (Marshal.StringToHGlobalAnsi (item));
|
|
|
|
}
|
|
|
|
|
2002-10-11 15:43:52 +00:00
|
|
|
public void Prepend (IntPtr raw)
|
|
|
|
{
|
|
|
|
list_ptr = Prepend (list_ptr, raw);
|
|
|
|
}
|
|
|
|
|
2002-09-01 04:46:38 +00:00
|
|
|
// 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))
|
2003-07-23 17:19:21 +00:00
|
|
|
ret = GLib.Object.GetObject (data, true);
|
2002-09-01 04:46:38 +00:00
|
|
|
|
|
|
|
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 ();
|
|
|
|
}
|
|
|
|
}
|