* qt/Makfile.am:
[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       bool notEmpty = dbus_message_iter_init_dict_iterator(iter, dictIter);
35
36       this.val = new Hashtable();
37
38       if (notEmpty) {
39         do {
40           string key = dbus_message_iter_get_dict_key(dictIter);
41           
42           // Get the argument type and get the value
43           Type elementType = (Type) DBus.Arguments.DBusTypes[(char) dbus_message_iter_get_arg_type(dictIter)];
44           object [] pars = new Object[2];
45           pars[0] = dictIter;
46           pars[1] = service;
47           DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars);
48           this.val.Add(key, dbusType);
49         } while (dbus_message_iter_next(dictIter));
50       }
51       
52       Marshal.FreeCoTaskMem(dictIter);
53     }
54     
55     public void Append(IntPtr iter)
56     {
57       IntPtr dictIter = Marshal.AllocCoTaskMem(Arguments.DBusMessageIterSize);
58
59       if (!dbus_message_iter_append_dict(iter,
60                                          dictIter)) {
61         throw new ApplicationException("Failed to append DICT argument:" + val);
62       }
63
64       foreach (DictionaryEntry entry in this.val) {
65         if (!dbus_message_iter_append_dict_key(dictIter, (string) entry.Key)) {
66           throw new ApplicationException("Failed to append DICT key:" + entry.Key);
67         }
68         
69         // Get the element type
70         Type elementType = Arguments.MatchType(entry.Value.GetType());
71         object [] pars = new Object[1];
72         pars[0] = entry.Value;
73         DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars);
74         dbusType.Append(dictIter);
75       }
76
77       Marshal.FreeCoTaskMem(dictIter);
78     }    
79
80     public static bool Suits(System.Type type) 
81     {
82       if (typeof(IDictionary).IsAssignableFrom(type)) {
83         return true;
84       }
85             
86       return false;
87     }
88
89     public static void EmitMarshalIn(ILGenerator generator, Type type)
90     {
91       if (type.IsByRef) {
92         generator.Emit(OpCodes.Ldind_Ref);
93       }
94     }
95
96     public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn) 
97     {
98       generator.Emit(OpCodes.Castclass, type);
99       if (!isReturn) {
100         generator.Emit(OpCodes.Stind_Ref);
101       }
102     }
103     
104     public object Get() 
105     {
106       return Get(typeof(Hashtable));
107     }
108
109     public object Get(System.Type type)
110     {
111       IDictionary retVal;
112
113       if (Suits(type)) {
114         retVal = (IDictionary) Activator.CreateInstance(type, new object[0]);
115         foreach (DictionaryEntry entry in this.val) {
116           retVal.Add(entry.Key, ((IDBusType) entry.Value).Get());
117         }
118       } else {
119         throw new ArgumentException("Cannot cast DBus.Type.Dict to type '" + type.ToString() + "'");
120       }
121         
122       return retVal;
123     }    
124
125     [DllImport("dbus-1")]
126     private extern static bool dbus_message_iter_init_dict_iterator(IntPtr iter,
127                                                                     IntPtr dictIter);
128  
129     [DllImport("dbus-1")]
130     private extern static bool dbus_message_iter_append_dict(IntPtr iter, 
131                                                              IntPtr dictIter);
132
133     [DllImport("dbus-1")]
134     private extern static bool dbus_message_iter_has_next(IntPtr iter);
135
136     [DllImport("dbus-1")]
137     private extern static bool dbus_message_iter_next(IntPtr iter);
138
139     [DllImport("dbus-1")]
140     private extern static string dbus_message_iter_get_dict_key (IntPtr dictIter);  
141
142     [DllImport("dbus-1")]
143     private extern static bool dbus_message_iter_append_dict_key (IntPtr dictIter,
144                                                                   string value);
145     [DllImport("dbus-1")]
146     private extern static int dbus_message_iter_get_arg_type(IntPtr iter);
147   }
148 }