00001 using System;
00002 using System.Collections;
00003 using System.Runtime.InteropServices;
00004 using System.Reflection.Emit;
00005
00006 using DBus;
00007
00008 namespace DBus.DBusType
00009 {
00013 public class Array : IDBusType
00014 {
00015 public const char Code = 'a';
00016 private System.Array val;
00017 private ArrayList elements;
00018 private Type elementType;
00019 private Service service = null;
00020
00021 private Array()
00022 {
00023 }
00024
00025 public Array(System.Array val, Service service)
00026 {
00027 this.val = val;
00028 this.elementType = Arguments.MatchType(val.GetType().UnderlyingSystemType);
00029 this.service = service;
00030 }
00031
00032 public Array(IntPtr iter, Service service)
00033 {
00034 this.service = service;
00035
00036 IntPtr arrayIter = Marshal.AllocCoTaskMem(Arguments.DBusMessageIterSize);
00037
00038 int elementTypeCode;
00039 bool notEmpty = dbus_message_iter_init_array_iterator(iter, arrayIter, out elementTypeCode);
00040 this.elementType = (Type) Arguments.DBusTypes[(char) elementTypeCode];
00041
00042 elements = new ArrayList();
00043
00044 if (notEmpty) {
00045 do {
00046 object [] pars = new Object[2];
00047 pars[0] = arrayIter;
00048 pars[1] = service;
00049 DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars);
00050 elements.Add(dbusType);
00051 } while (dbus_message_iter_next(arrayIter));
00052 }
00053
00054 Marshal.FreeCoTaskMem(arrayIter);
00055 }
00056
00057 public void Append(IntPtr iter)
00058 {
00059 IntPtr arrayIter = Marshal.AllocCoTaskMem(Arguments.DBusMessageIterSize);
00060
00061 if (!dbus_message_iter_append_array(iter,
00062 arrayIter,
00063 (int) Arguments.GetCode(this.elementType))) {
00064 throw new ApplicationException("Failed to append INT32 argument:" + val);
00065 }
00066
00067 foreach (object element in this.val) {
00068 object [] pars = new Object[2];
00069 pars[0] = element;
00070 pars[1] = this.service;
00071 DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars);
00072 dbusType.Append(arrayIter);
00073 }
00074
00075 Marshal.FreeCoTaskMem(arrayIter);
00076 }
00077
00078 public static bool Suits(System.Type type)
00079 {
00080 if (type.IsArray) {
00081 return true;
00082 }
00083
00084 return false;
00085 }
00086
00087 public static void EmitMarshalIn(ILGenerator generator, Type type)
00088 {
00089 if (type.IsByRef) {
00090 generator.Emit(OpCodes.Ldind_Ref);
00091 }
00092 }
00093
00094 public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn)
00095 {
00096 generator.Emit(OpCodes.Castclass, type);
00097 if (!isReturn) {
00098 generator.Emit(OpCodes.Stind_Ref);
00099 }
00100 }
00101
00102 public object Get()
00103 {
00104 throw new ArgumentException("Cannot call Get on an Array without specifying type.");
00105 }
00106
00107 public object Get(System.Type type)
00108 {
00109 if (type.IsArray)
00110 type = type.GetElementType ();
00111
00112 if (Arguments.Suits(elementType, type.UnderlyingSystemType)) {
00113 this.val = System.Array.CreateInstance(type.UnderlyingSystemType, elements.Count);
00114 int i = 0;
00115 foreach (DBusType.IDBusType element in elements) {
00116 this.val.SetValue(element.Get(type.UnderlyingSystemType), i++);
00117 }
00118 } else {
00119 throw new ArgumentException("Cannot cast DBus.Type.Array to type '" + type.ToString() + "'");
00120 }
00121
00122 return this.val;
00123 }
00124
00125 [DllImport("dbus-1")]
00126 private extern static bool dbus_message_iter_init_array_iterator(IntPtr iter,
00127 IntPtr arrayIter,
00128 out int elementType);
00129
00130 [DllImport("dbus-1")]
00131 private extern static bool dbus_message_iter_append_array(IntPtr iter,
00132 IntPtr arrayIter,
00133 int elementType);
00134
00135 [DllImport("dbus-1")]
00136 private extern static bool dbus_message_iter_has_next(IntPtr iter);
00137
00138 [DllImport("dbus-1")]
00139 private extern static bool dbus_message_iter_next(IntPtr iter);
00140 }
00141 }