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