1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Reflection.Emit;
using DBus;
namespace DBus.DBusType
{
/// <summary>
/// Array.
/// </summary>
public class Array : IDBusType
{
public const char Code = 'a';
private System.Array val;
private ArrayList elements;
private Type elementType;
private Service service = null;
private Array()
{
}
public Array(System.Array val, Service service)
{
this.val = val;
this.elementType = Arguments.MatchType(val.GetType().GetElementType());
this.service = service;
}
public Array(IntPtr iter, Service service)
{
this.service = service;
IntPtr arrayIter = Marshal.AllocCoTaskMem(Arguments.DBusMessageIterSize);
int elementTypeCode = dbus_message_iter_get_element_type (iter);
dbus_message_iter_recurse (iter, arrayIter);
this.elementType = (Type) Arguments.DBusTypes [(char) elementTypeCode];
elements = new ArrayList ();
if (dbus_message_iter_get_arg_type (arrayIter) != 0) {
do {
object [] pars = new Object[2];
pars[0] = arrayIter;
pars[1] = service;
DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars);
elements.Add(dbusType);
} while (dbus_message_iter_next(arrayIter));
}
Marshal.FreeCoTaskMem(arrayIter);
}
public string GetElementCodeAsString ()
{
string ret = System.String.Empty;
Type t = val.GetType ().GetElementType ();
while (true) {
ret += Arguments.GetCodeAsString (Arguments.MatchType(t));
if (t.IsArray)
t = t.GetElementType ();
else
break;
}
return ret;
}
public void Append(IntPtr iter)
{
IntPtr arrayIter = Marshal.AllocCoTaskMem (Arguments.DBusMessageIterSize);
if (!dbus_message_iter_open_container (iter,
(int) Code, GetElementCodeAsString(),
arrayIter)) {
throw new ApplicationException("Failed to append array argument: " + val);
}
foreach (object element in this.val) {
object [] pars = new Object[2];
pars[0] = element;
pars[1] = this.service;
DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars);
dbusType.Append(arrayIter);
}
if (!dbus_message_iter_close_container (iter, arrayIter)) {
throw new ApplicationException ("Failed to append array argument: " + val);
}
Marshal.FreeCoTaskMem (arrayIter);
}
public static bool Suits(System.Type type)
{
Type type2 = type.GetElementType ();
if (type.IsArray || (type2 != null && type2.IsArray)) {
return true;
}
return false;
}
public static void EmitMarshalIn(ILGenerator generator, Type type)
{
if (type.IsByRef) {
generator.Emit(OpCodes.Ldind_Ref);
}
}
public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn)
{
generator.Emit(OpCodes.Castclass, type);
if (!isReturn) {
generator.Emit(OpCodes.Stind_Ref);
}
}
public object Get()
{
throw new ArgumentException("Cannot call Get on an Array without specifying type.");
}
public object Get(System.Type type)
{
if (type.IsArray)
type = type.GetElementType ();
if (Arguments.Suits(elementType, type.UnderlyingSystemType)) {
this.val = System.Array.CreateInstance(type.UnderlyingSystemType, elements.Count);
int i = 0;
foreach (DBusType.IDBusType element in elements) {
this.val.SetValue(element.Get(type.UnderlyingSystemType), i++);
}
} else {
throw new ArgumentException("Cannot cast DBus.Type.Array to type '" + type.ToString() + "'");
}
return this.val;
}
[DllImport("dbus-1")]
private extern static bool dbus_message_iter_open_container (IntPtr iter,
int containerType,
string elementType,
IntPtr subIter);
[DllImport("dbus-1")]
private extern static bool dbus_message_iter_close_container (IntPtr iter,
IntPtr subIter);
[DllImport("dbus-1")]
private extern static int dbus_message_iter_get_element_type(IntPtr iter);
[DllImport("dbus-1")]
private extern static int dbus_message_iter_get_arg_type(IntPtr iter);
[DllImport("dbus-1")]
private extern static void dbus_message_iter_recurse(IntPtr iter, IntPtr subIter);
[DllImport("dbus-1")]
private extern static bool dbus_message_iter_next(IntPtr iter);
[DllImport("dbus-1")]
private extern static bool dbus_message_iter_has_next (IntPtr iter);
}
}
|