Made all DBusTypes take Service in the constructor because Array also needed it in...
[platform/upstream/dbus.git] / mono / DBusType / Dict.cs
1 using System;
2 using System.Collections;
3 using System.Runtime.InteropServices;
4 using System.Reflection.Emit;
5
6 using DBus;
7
8 namespace DBus.DBusType
9 {
10   /// <summary>
11   /// Dict.
12   /// </summary>
13   public class Dict : IDBusType
14   {
15     public const char Code = 'm';
16     private Hashtable val;
17     
18     private Dict()
19     {
20     }
21     
22     public Dict(IDictionary val, Service service)
23     {
24       this.val = new Hashtable();
25       foreach (DictionaryEntry entry in val) {
26         this.val.Add(entry.Key, entry.Value);
27       }
28     }
29
30     public Dict(IntPtr iter, Service service)
31     {
32       IntPtr dictIter = Marshal.AllocCoTaskMem(Arguments.DBusMessageIterSize);
33       
34       dbus_message_iter_init_dict_iterator(iter, dictIter);
35
36       this.val = new Hashtable();
37
38       do {
39         string key = dbus_message_iter_get_dict_key(dictIter);
40
41         // Get the argument type and get the value
42         Type elementType = (Type) DBus.Arguments.DBusTypes[(char) dbus_message_iter_get_arg_type(dictIter)];
43         object [] pars = new Object[1];
44         pars[0] = dictIter;
45         DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars);
46         this.val.Add(key, dbusType);
47       } while (dbus_message_iter_next(dictIter));
48       
49       Marshal.FreeCoTaskMem(dictIter);
50     }
51     
52     public void Append(IntPtr iter)
53     {
54       IntPtr dictIter = Marshal.AllocCoTaskMem(Arguments.DBusMessageIterSize);
55
56       if (!dbus_message_iter_append_dict(iter,
57                                          dictIter)) {
58         throw new ApplicationException("Failed to append DICT argument:" + val);
59       }
60
61       foreach (DictionaryEntry entry in this.val) {
62         if (!dbus_message_iter_append_dict_key(dictIter, (string) entry.Key)) {
63           throw new ApplicationException("Failed to append DICT key:" + entry.Key);
64         }
65         
66         // Get the element type
67         Type elementType = Arguments.MatchType(entry.Value.GetType());
68         object [] pars = new Object[1];
69         pars[0] = entry.Value;
70         DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars);
71         dbusType.Append(dictIter);
72       }
73
74       Marshal.FreeCoTaskMem(dictIter);
75     }    
76
77     public static bool Suits(System.Type type) 
78     {
79       if (typeof(IDictionary).IsAssignableFrom(type)) {
80         return true;
81       }
82             
83       return false;
84     }
85
86     public static void EmitMarshalIn(ILGenerator generator, Type type)
87     {
88       if (type.IsByRef) {
89         generator.Emit(OpCodes.Ldind_Ref);
90       }
91     }
92
93     public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn) 
94     {
95       generator.Emit(OpCodes.Castclass, type);
96       if (!isReturn) {
97         generator.Emit(OpCodes.Stind_Ref);
98       }
99     }
100     
101     public object Get() 
102     {
103       return Get(typeof(Hashtable));
104     }
105
106     public object Get(System.Type type)
107     {
108       IDictionary retVal;
109
110       if (Suits(type)) {
111         retVal = (IDictionary) Activator.CreateInstance(type, new object[0]);
112         foreach (DictionaryEntry entry in this.val) {
113           retVal.Add(entry.Key, ((IDBusType) entry.Value).Get());
114         }
115       } else {
116         throw new ArgumentException("Cannot cast DBus.Type.Dict to type '" + type.ToString() + "'");
117       }
118         
119       return retVal;
120     }    
121
122     [DllImport("dbus-1")]
123     private extern static void dbus_message_iter_init_dict_iterator(IntPtr iter,
124                                                                     IntPtr dictIter);
125  
126     [DllImport("dbus-1")]
127     private extern static bool dbus_message_iter_append_dict(IntPtr iter, 
128                                                              IntPtr dictIter);
129
130     [DllImport("dbus-1")]
131     private extern static bool dbus_message_iter_has_next(IntPtr iter);
132
133     [DllImport("dbus-1")]
134     private extern static bool dbus_message_iter_next(IntPtr iter);
135
136     [DllImport("dbus-1")]
137     private extern static string dbus_message_iter_get_dict_key (IntPtr dictIter);  
138
139     [DllImport("dbus-1")]
140     private extern static bool dbus_message_iter_append_dict_key (IntPtr dictIter,
141                                                                   string value);
142     [DllImport("dbus-1")]
143     private extern static int dbus_message_iter_get_arg_type(IntPtr iter);
144   }
145 }