Handle empty iterators.
[platform/upstream/dbus.git] / mono / DBusType / Custom.cs
1 using System;
2 using System.Runtime.InteropServices;
3 using System.Reflection.Emit;
4
5 using DBus;
6
7 namespace DBus.DBusType
8 {
9   /// <summary>
10   /// A named byte array, used for custom types.
11   /// </summary>
12   public class Custom : IDBusType
13   {
14     public const char Code = 'c';
15     private DBus.Custom val;
16     
17     private Custom()
18     {
19     }
20     
21     public Custom(DBus.Custom val, Service service) 
22     {
23       this.val = val;
24     }
25
26     public Custom(IntPtr iter, Service service)
27     {
28       string name;
29       IntPtr value;
30       int len;
31
32       if (!dbus_message_iter_get_custom(iter, out name, out value, out len)) {
33         throw new ApplicationException("Failed to get CUSTOM argument.");
34       }
35
36       this.val.Name = name;
37       this.val.Data = new byte[len];
38       Marshal.Copy(value, this.val.Data, 0, len);
39     }
40     
41     public void Append(IntPtr iter)
42     {
43       IntPtr data = Marshal.AllocCoTaskMem(this.val.Data.Length);
44       try {
45         Marshal.Copy(this.val.Data, 0, data, this.val.Data.Length);
46         if (!dbus_message_iter_append_custom(iter, this.val.Name, data, this.val.Data.Length)) {
47           throw new ApplicationException("Failed to append CUSTOM argument:" + val);
48         }
49       } finally {
50         Marshal.FreeCoTaskMem(data);
51       }
52     }
53
54     public static bool Suits(System.Type type) 
55     {
56       switch (type.ToString()) {
57       case "DBus.Custom":
58       case "DBus.Custom&":
59         return true;
60       }
61       
62       return false;
63     }
64
65     public static void EmitMarshalIn(ILGenerator generator, Type type)
66     {
67       if (type.IsByRef) {
68         generator.Emit(OpCodes.Ldobj, type);
69       }
70     }
71
72     public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn) 
73     {
74       generator.Emit(OpCodes.Unbox, type);
75       generator.Emit(OpCodes.Ldobj, type);
76       if (!isReturn) {
77         generator.Emit(OpCodes.Stobj, type);
78       }
79     }
80     
81     public object Get() 
82     {
83       return this.val;
84     }
85
86     public object Get(System.Type type)
87     {
88       switch (type.ToString()) {
89       case "DBus.Custom":
90       case "DBus.Custom&":
91         return this.val;
92       default:
93         throw new ArgumentException("Cannot cast DBus.Type.Custom to type '" + type.ToString() + "'");
94       }
95     }
96
97     [DllImport("dbus-1")]
98     private extern static bool dbus_message_iter_get_custom(IntPtr iter,
99                                                             out string name,
100                                                             out IntPtr value,
101                                                             out int len);
102  
103     [DllImport("dbus-1")]
104     private extern static bool dbus_message_iter_append_custom(IntPtr iter, 
105                                                                string name,
106                                                                IntPtr data,
107                                                                int len);
108   }
109 }