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().GetElementType());
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 = dbus_message_iter_get_element_type (iter);
00039 dbus_message_iter_recurse (iter, arrayIter);
00040 this.elementType = (Type) Arguments.DBusTypes [(char) elementTypeCode];
00041
00042 elements = new ArrayList ();
00043
00044 if (dbus_message_iter_get_arg_type (arrayIter) != 0) {
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 string GetElementCodeAsString ()
00058 {
00059 string ret = System.String.Empty;
00060 Type t = val.GetType ().GetElementType ();
00061
00062 while (true) {
00063 ret += Arguments.GetCodeAsString (Arguments.MatchType(t));
00064
00065 if (t.IsArray)
00066 t = t.GetElementType ();
00067 else
00068 break;
00069 }
00070
00071 return ret;
00072 }
00073
00074 public void Append(IntPtr iter)
00075 {
00076 IntPtr arrayIter = Marshal.AllocCoTaskMem (Arguments.DBusMessageIterSize);
00077
00078 if (!dbus_message_iter_open_container (iter,
00079 (int) Code, GetElementCodeAsString(),
00080 arrayIter)) {
00081 throw new ApplicationException("Failed to append array argument: " + val);
00082 }
00083
00084 foreach (object element in this.val) {
00085 object [] pars = new Object[2];
00086 pars[0] = element;
00087 pars[1] = this.service;
00088 DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars);
00089 dbusType.Append(arrayIter);
00090 }
00091
00092 if (!dbus_message_iter_close_container (iter, arrayIter)) {
00093 throw new ApplicationException ("Failed to append array argument: " + val);
00094 }
00095
00096 Marshal.FreeCoTaskMem (arrayIter);
00097 }
00098
00099 public static bool Suits(System.Type type)
00100 {
00101 Type type2 = type.GetElementType ();
00102 if (type.IsArray || (type2 != null && type2.IsArray)) {
00103 return true;
00104 }
00105
00106 return false;
00107 }
00108
00109 public static void EmitMarshalIn(ILGenerator generator, Type type)
00110 {
00111 if (type.IsByRef) {
00112 generator.Emit(OpCodes.Ldind_Ref);
00113 }
00114 }
00115
00116 public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn)
00117 {
00118 generator.Emit(OpCodes.Castclass, type);
00119 if (!isReturn) {
00120 generator.Emit(OpCodes.Stind_Ref);
00121 }
00122 }
00123
00124 public object Get()
00125 {
00126 throw new ArgumentException("Cannot call Get on an Array without specifying type.");
00127 }
00128
00129 public object Get(System.Type type)
00130 {
00131 if (type.IsArray)
00132 type = type.GetElementType ();
00133
00134 if (Arguments.Suits(elementType, type.UnderlyingSystemType)) {
00135 this.val = System.Array.CreateInstance(type.UnderlyingSystemType, elements.Count);
00136 int i = 0;
00137 foreach (DBusType.IDBusType element in elements) {
00138 this.val.SetValue(element.Get(type.UnderlyingSystemType), i++);
00139 }
00140 } else {
00141 throw new ArgumentException("Cannot cast DBus.Type.Array to type '" + type.ToString() + "'");
00142 }
00143
00144 return this.val;
00145 }
00146
00147 [DllImport("dbus-1")]
00148 private extern static bool dbus_message_iter_open_container (IntPtr iter,
00149 int containerType,
00150 string elementType,
00151 IntPtr subIter);
00152
00153 [DllImport("dbus-1")]
00154 private extern static bool dbus_message_iter_close_container (IntPtr iter,
00155 IntPtr subIter);
00156
00157 [DllImport("dbus-1")]
00158 private extern static int dbus_message_iter_get_element_type(IntPtr iter);
00159
00160 [DllImport("dbus-1")]
00161 private extern static int dbus_message_iter_get_arg_type(IntPtr iter);
00162
00163 [DllImport("dbus-1")]
00164 private extern static void dbus_message_iter_recurse(IntPtr iter, IntPtr subIter);
00165
00166 [DllImport("dbus-1")]
00167 private extern static bool dbus_message_iter_next(IntPtr iter);
00168
00169 [DllImport("dbus-1")]
00170 private extern static bool dbus_message_iter_has_next (IntPtr iter);
00171 }
00172 }