~ubuntu-branches/ubuntu/lucid/tomboy/lucid-proposed

« back to all changes in this revision

Viewing changes to Tomboy/dbus-sharp/dbus-sharp/src/MessageWriter.cs

Tags: upstream-0.9.7
ImportĀ upstreamĀ versionĀ 0.9.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Copyright 2006 Alp Toker <alp@atoker.com>
2
 
// This software is made available under the MIT License
3
 
// See COPYING for details
4
 
 
5
 
using System;
6
 
using System.Text;
7
 
using System.Collections.Generic;
8
 
using System.IO;
9
 
using System.Reflection;
10
 
 
11
 
namespace NDesk.DBus
12
 
{
13
 
        class MessageWriter
14
 
        {
15
 
                protected EndianFlag endianness;
16
 
                protected MemoryStream stream;
17
 
 
18
 
                public Connection connection;
19
 
 
20
 
                //a default constructor is a bad idea for now as we want to make sure the header and content-type match
21
 
                //public MessageWriter () : this (Connection.NativeEndianness)
22
 
 
23
 
                public MessageWriter (EndianFlag endianness)
24
 
                {
25
 
                        this.endianness = endianness;
26
 
                        stream = new MemoryStream ();
27
 
                }
28
 
 
29
 
                public byte[] ToArray ()
30
 
                {
31
 
                        //TODO: mark the writer locked or something here
32
 
                        return stream.ToArray ();
33
 
                }
34
 
 
35
 
                public void CloseWrite ()
36
 
                {
37
 
                        int needed = Protocol.PadNeeded ((int)stream.Position, 8);
38
 
                        for (int i = 0 ; i != needed ; i++)
39
 
                                stream.WriteByte (0);
40
 
                }
41
 
 
42
 
                public void Write (byte val)
43
 
                {
44
 
                        stream.WriteByte (val);
45
 
                }
46
 
 
47
 
                public void Write (bool val)
48
 
                {
49
 
                        Write ((uint) (val ? 1 : 0));
50
 
                }
51
 
 
52
 
                unsafe protected void MarshalUShort (byte *data)
53
 
                {
54
 
                        WritePad (2);
55
 
                        byte[] dst = new byte[2];
56
 
 
57
 
                        if (endianness == Connection.NativeEndianness) {
58
 
                                dst[0] = data[0];
59
 
                                dst[1] = data[1];
60
 
                        } else {
61
 
                                dst[0] = data[1];
62
 
                                dst[1] = data[0];
63
 
                        }
64
 
 
65
 
                        stream.Write (dst, 0, 2);
66
 
                }
67
 
 
68
 
                unsafe public void Write (short val)
69
 
                {
70
 
                        MarshalUShort ((byte*)&val);
71
 
                }
72
 
 
73
 
                unsafe public void Write (ushort val)
74
 
                {
75
 
                        MarshalUShort ((byte*)&val);
76
 
                }
77
 
 
78
 
                unsafe protected void MarshalUInt (byte *data)
79
 
                {
80
 
                        WritePad (4);
81
 
                        byte[] dst = new byte[4];
82
 
 
83
 
                        if (endianness == Connection.NativeEndianness) {
84
 
                                dst[0] = data[0];
85
 
                                dst[1] = data[1];
86
 
                                dst[2] = data[2];
87
 
                                dst[3] = data[3];
88
 
                        } else {
89
 
                                dst[0] = data[3];
90
 
                                dst[1] = data[2];
91
 
                                dst[2] = data[1];
92
 
                                dst[3] = data[0];
93
 
                        }
94
 
 
95
 
                        stream.Write (dst, 0, 4);
96
 
                }
97
 
 
98
 
                unsafe public void Write (int val)
99
 
                {
100
 
                        MarshalUInt ((byte*)&val);
101
 
                }
102
 
 
103
 
                unsafe public void Write (uint val)
104
 
                {
105
 
                        MarshalUInt ((byte*)&val);
106
 
                }
107
 
 
108
 
                unsafe protected void MarshalULong (byte *data)
109
 
                {
110
 
                        WritePad (8);
111
 
                        byte[] dst = new byte[8];
112
 
 
113
 
                        if (endianness == Connection.NativeEndianness) {
114
 
                                for (int i = 0; i < 8; ++i)
115
 
                                        dst[i] = data[i];
116
 
                        } else {
117
 
                                for (int i = 0; i < 8; ++i)
118
 
                                        dst[i] = data[7 - i];
119
 
                        }
120
 
 
121
 
                        stream.Write (dst, 0, 8);
122
 
                }
123
 
 
124
 
                unsafe public void Write (long val)
125
 
                {
126
 
                        MarshalULong ((byte*)&val);
127
 
                }
128
 
 
129
 
                unsafe public void Write (ulong val)
130
 
                {
131
 
                        MarshalULong ((byte*)&val);
132
 
                }
133
 
 
134
 
#if !DISABLE_SINGLE
135
 
                unsafe public void Write (float val)
136
 
                {
137
 
                        MarshalUInt ((byte*)&val);
138
 
                }
139
 
#endif
140
 
 
141
 
                unsafe public void Write (double val)
142
 
                {
143
 
                        MarshalULong ((byte*)&val);
144
 
                }
145
 
 
146
 
                public void Write (string val)
147
 
                {
148
 
                        byte[] utf8_data = Encoding.UTF8.GetBytes (val);
149
 
                        Write ((uint)utf8_data.Length);
150
 
                        stream.Write (utf8_data, 0, utf8_data.Length);
151
 
                        stream.WriteByte (0); //NULL string terminator
152
 
                }
153
 
 
154
 
                public void Write (ObjectPath val)
155
 
                {
156
 
                        Write (val.Value);
157
 
                }
158
 
 
159
 
                public void Write (Signature val)
160
 
                {
161
 
                        byte[] ascii_data = val.GetBuffer ();
162
 
                        Write ((byte)ascii_data.Length);
163
 
                        stream.Write (ascii_data, 0, ascii_data.Length);
164
 
                        stream.WriteByte (0); //NULL signature terminator
165
 
                }
166
 
 
167
 
                public void Write (Type type, object val)
168
 
                {
169
 
                        if (type == typeof (void))
170
 
                                return;
171
 
 
172
 
                        if (type.IsArray) {
173
 
                                Write (type, (Array)val);
174
 
                        } else if (type == typeof (ObjectPath)) {
175
 
                                Write ((ObjectPath)val);
176
 
                        } else if (type == typeof (Signature)) {
177
 
                                Write ((Signature)val);
178
 
                        } else if (type == typeof (object)) {
179
 
                                Write (val);
180
 
                        } else if (type == typeof (string)) {
181
 
                                Write ((string)val);
182
 
                        } else if (type.IsGenericType && (type.GetGenericTypeDefinition () == typeof (IDictionary<,>) || type.GetGenericTypeDefinition () == typeof (Dictionary<,>))) {
183
 
                                Type[] genArgs = type.GetGenericArguments ();
184
 
                                System.Collections.IDictionary idict = (System.Collections.IDictionary)val;
185
 
                                WriteFromDict (genArgs[0], genArgs[1], idict);
186
 
                        } else if (Mapper.IsPublic (type)) {
187
 
                                WriteObject (type, val);
188
 
                        } else if (!type.IsPrimitive && !type.IsEnum) {
189
 
                                WriteStruct (type, val);
190
 
                                /*
191
 
                        } else if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (Nullable<>)) {
192
 
                                //is it possible to support nullable types?
193
 
                                Type[] genArgs = type.GetGenericArguments ();
194
 
                                WriteVariant (genArgs[0], val);
195
 
                                */
196
 
                        } else {
197
 
                                Write (Signature.TypeToDType (type), val);
198
 
                        }
199
 
                }
200
 
 
201
 
                //helper method, should not be used as it boxes needlessly
202
 
                public void Write (DType dtype, object val)
203
 
                {
204
 
                        switch (dtype)
205
 
                        {
206
 
                                case DType.Byte:
207
 
                                {
208
 
                                        Write ((byte)val);
209
 
                                }
210
 
                                break;
211
 
                                case DType.Boolean:
212
 
                                {
213
 
                                        Write ((bool)val);
214
 
                                }
215
 
                                break;
216
 
                                case DType.Int16:
217
 
                                {
218
 
                                        Write ((short)val);
219
 
                                }
220
 
                                break;
221
 
                                case DType.UInt16:
222
 
                                {
223
 
                                        Write ((ushort)val);
224
 
                                }
225
 
                                break;
226
 
                                case DType.Int32:
227
 
                                {
228
 
                                        Write ((int)val);
229
 
                                }
230
 
                                break;
231
 
                                case DType.UInt32:
232
 
                                {
233
 
                                        Write ((uint)val);
234
 
                                }
235
 
                                break;
236
 
                                case DType.Int64:
237
 
                                {
238
 
                                        Write ((long)val);
239
 
                                }
240
 
                                break;
241
 
                                case DType.UInt64:
242
 
                                {
243
 
                                        Write ((ulong)val);
244
 
                                }
245
 
                                break;
246
 
#if !DISABLE_SINGLE
247
 
                                case DType.Single:
248
 
                                {
249
 
                                        Write ((float)val);
250
 
                                }
251
 
                                break;
252
 
#endif
253
 
                                case DType.Double:
254
 
                                {
255
 
                                        Write ((double)val);
256
 
                                }
257
 
                                break;
258
 
                                case DType.String:
259
 
                                {
260
 
                                        Write ((string)val);
261
 
                                }
262
 
                                break;
263
 
                                case DType.ObjectPath:
264
 
                                {
265
 
                                        Write ((ObjectPath)val);
266
 
                                }
267
 
                                break;
268
 
                                case DType.Signature:
269
 
                                {
270
 
                                        Write ((Signature)val);
271
 
                                }
272
 
                                break;
273
 
                                case DType.Variant:
274
 
                                {
275
 
                                        Write ((object)val);
276
 
                                }
277
 
                                break;
278
 
                                default:
279
 
                                throw new Exception ("Unhandled D-Bus type: " + dtype);
280
 
                        }
281
 
                }
282
 
 
283
 
                public void WriteObject (Type type, object val)
284
 
                {
285
 
                        ObjectPath path;
286
 
 
287
 
                        BusObject bobj = val as BusObject;
288
 
 
289
 
                        if (bobj == null && val is MarshalByRefObject) {
290
 
                                bobj = ((MarshalByRefObject)val).GetLifetimeService () as BusObject;
291
 
                        }
292
 
 
293
 
                        if (bobj == null)
294
 
                                throw new Exception ("No object reference to write");
295
 
 
296
 
                        path = bobj.Path;
297
 
 
298
 
                        Write (path);
299
 
                }
300
 
 
301
 
                //variant
302
 
                public void Write (object val)
303
 
                {
304
 
                        //TODO: maybe support sending null variants
305
 
 
306
 
                        if (val == null)
307
 
                                throw new NotSupportedException ("Cannot send null variant");
308
 
 
309
 
                        Type type = val.GetType ();
310
 
 
311
 
                        WriteVariant (type, val);
312
 
                }
313
 
 
314
 
                public void WriteVariant (Type type, object val)
315
 
                {
316
 
                        Signature sig = Signature.GetSig (type);
317
 
 
318
 
                        Write (sig);
319
 
                        Write (type, val);
320
 
                }
321
 
 
322
 
                //this requires a seekable stream for now
323
 
                public void Write (Type type, Array val)
324
 
                {
325
 
                        Type elemType = type.GetElementType ();
326
 
 
327
 
                        //TODO: more fast paths for primitive arrays
328
 
                        if (elemType == typeof (byte)) {
329
 
                                Write ((uint)val.Length);
330
 
                                stream.Write ((byte[])val, 0, val.Length);
331
 
                                return;
332
 
                        }
333
 
 
334
 
                        Write ((uint)0);
335
 
                        long lengthPos = stream.Position - 4;
336
 
 
337
 
                        //advance to the alignment of the element
338
 
                        WritePad (Protocol.GetAlignment (Signature.TypeToDType (elemType)));
339
 
 
340
 
                        long startPos = stream.Position;
341
 
 
342
 
                        foreach (object elem in val)
343
 
                                Write (elemType, elem);
344
 
 
345
 
                        long endPos = stream.Position;
346
 
 
347
 
                        stream.Position = lengthPos;
348
 
                        Write ((uint)(endPos - startPos));
349
 
 
350
 
                        stream.Position = endPos;
351
 
                }
352
 
 
353
 
                public void WriteFromDict (Type keyType, Type valType, System.Collections.IDictionary val)
354
 
                {
355
 
                        Write ((uint)0);
356
 
                        long lengthPos = stream.Position - 4;
357
 
 
358
 
                        //advance to the alignment of the element
359
 
                        //WritePad (Protocol.GetAlignment (Signature.TypeToDType (type)));
360
 
                        WritePad (8);
361
 
 
362
 
                        long startPos = stream.Position;
363
 
 
364
 
                        foreach (System.Collections.DictionaryEntry entry in val)
365
 
                        {
366
 
                                WritePad (8);
367
 
 
368
 
                                Write (keyType, entry.Key);
369
 
                                Write (valType, entry.Value);
370
 
                        }
371
 
 
372
 
                        long endPos = stream.Position;
373
 
 
374
 
                        stream.Position = lengthPos;
375
 
                        Write ((uint)(endPos - startPos));
376
 
 
377
 
                        stream.Position = endPos;
378
 
                }
379
 
 
380
 
                public void WriteStruct (Type type, object val)
381
 
                {
382
 
                        WritePad (8); //offset for structs, right?
383
 
 
384
 
                        /*
385
 
                        ConstructorInfo[] cis = type.GetConstructors ();
386
 
                        if (cis.Length != 0) {
387
 
                                System.Reflection.ParameterInfo[]  parms = ci.GetParameters ();
388
 
 
389
 
                                foreach (ParameterInfo parm in parms) {
390
 
                                }
391
 
                        }
392
 
                        */
393
 
                        if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (KeyValuePair<,>)) {
394
 
                                System.Reflection.PropertyInfo key_prop = type.GetProperty ("Key");
395
 
                                Write (key_prop.PropertyType, key_prop.GetValue (val, null));
396
 
 
397
 
                                System.Reflection.PropertyInfo val_prop = type.GetProperty ("Value");
398
 
                                Write (val_prop.PropertyType, val_prop.GetValue (val, null));
399
 
 
400
 
                                return;
401
 
                        }
402
 
 
403
 
                        FieldInfo[] fis = type.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
404
 
 
405
 
                        foreach (System.Reflection.FieldInfo fi in fis) {
406
 
                                object elem;
407
 
                                //public virtual object GetValueDirect (TypedReference obj);
408
 
                                elem = fi.GetValue (val);
409
 
                                //Write (Signature.TypeToDType (fi.FieldType), elem);
410
 
                                Write (fi.FieldType, elem);
411
 
                        }
412
 
                }
413
 
 
414
 
                public void WritePad (int alignment)
415
 
                {
416
 
                        stream.Position = Protocol.Padded ((int)stream.Position, alignment);
417
 
                }
418
 
        }
419
 
}