~ubuntu-branches/debian/jessie/banshee-community-extensions/jessie

« back to all changes in this revision

Viewing changes to .pc/0001-Use-DBus-instead-of-NDesk.DBus.patch/src/Telepathy/Banshee.Telepathy/NDesk.DBus/MessageReader.cs

  • Committer: Package Import Robot
  • Author(s): Chow Loong Jin
  • Date: 2011-09-20 18:45:46 UTC
  • mfrom: (1.2.9 upstream) (5.1.8 experimental)
  • Revision ID: package-import@ubuntu.com-20110920184546-3ahue2qplydc4t0e
Tags: 2.2.0-1
* [4940fab] Imported Upstream version 2.2.0
  + Notable bug fixes:
    - Karaoke: Fix crash when switching to Now Playing
    - Lyrics: Fix crash when switching to Now Playing

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
 
        partial class MessageReader
14
 
        {
15
 
                protected EndianFlag endianness;
16
 
                //protected byte[] data;
17
 
                public byte[] data;
18
 
                //TODO: this should be uint or long to handle long messages
19
 
                //internal int pos = 0;
20
 
                public int pos = 0;
21
 
                protected Message message;
22
 
 
23
 
                public MessageReader (EndianFlag endianness, byte[] data)
24
 
                {
25
 
                        //if (data == null)
26
 
                        //      throw new ArgumentNullException ("data");
27
 
                        if (data == null)
28
 
                                data = new byte[0];
29
 
 
30
 
                        this.endianness = endianness;
31
 
                        this.IsNativeEndian = endianness == Connection.NativeEndianness;
32
 
                        this.data = data;
33
 
                }
34
 
 
35
 
                public MessageReader (Message message) : this (message.Header.Endianness, message.Body)
36
 
                {
37
 
                        if (message == null)
38
 
                                throw new ArgumentNullException ("message");
39
 
 
40
 
                        this.message = message;
41
 
                }
42
 
 
43
 
                public readonly bool IsNativeEndian;
44
 
 
45
 
                public object ReadValue (Type type)
46
 
                {
47
 
                        if (type == typeof (void))
48
 
                                return null;
49
 
 
50
 
                        if (type.IsArray) {
51
 
                                return ReadArray (type.GetElementType ());
52
 
                        } else if (type == typeof (ObjectPath)) {
53
 
                                return ReadObjectPath ();
54
 
                        } else if (type == typeof (Signature)) {
55
 
                                return ReadSignature ();
56
 
                        } else if (type == typeof (object)) {
57
 
                                return ReadVariant ();
58
 
                        } else if (type == typeof (string)) {
59
 
                                return ReadString ();
60
 
                        } else if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (IDictionary<,>)) {
61
 
                                Type[] genArgs = type.GetGenericArguments ();
62
 
                                //Type dictType = typeof (Dictionary<,>).MakeGenericType (genArgs);
63
 
                                //workaround for Mono bug #81035 (memory leak)
64
 
                                Type dictType = Mapper.GetGenericType (typeof (Dictionary<,>), genArgs);
65
 
                                System.Collections.IDictionary idict = (System.Collections.IDictionary)Activator.CreateInstance(dictType, new object[0]);
66
 
                                GetValueToDict (genArgs[0], genArgs[1], idict);
67
 
                                return idict;
68
 
                        } else if (Mapper.IsPublic (type)) {
69
 
                                return GetObject (type);
70
 
                        } else if (!type.IsPrimitive && !type.IsEnum) {
71
 
                                return ReadStruct (type);
72
 
                        } else {
73
 
                                object val;
74
 
                                DType dtype = Signature.TypeToDType (type);
75
 
                                val = ReadValue (dtype);
76
 
 
77
 
                                if (type.IsEnum)
78
 
                                        val = Enum.ToObject (type, val);
79
 
 
80
 
                                return val;
81
 
                        }
82
 
                }
83
 
 
84
 
                //helper method, should not be used generally
85
 
                public object ReadValue (DType dtype)
86
 
                {
87
 
                        switch (dtype)
88
 
                        {
89
 
                                case DType.Byte:
90
 
                                        return ReadByte ();
91
 
 
92
 
                                case DType.Boolean:
93
 
                                        return ReadBoolean ();
94
 
 
95
 
                                case DType.Int16:
96
 
                                        return ReadInt16 ();
97
 
 
98
 
                                case DType.UInt16:
99
 
                                        return ReadUInt16 ();
100
 
 
101
 
                                case DType.Int32:
102
 
                                        return ReadInt32 ();
103
 
 
104
 
                                case DType.UInt32:
105
 
                                        return ReadUInt32 ();
106
 
 
107
 
                                case DType.Int64:
108
 
                                        return ReadInt64 ();
109
 
 
110
 
                                case DType.UInt64:
111
 
                                        return ReadUInt64 ();
112
 
 
113
 
#if !DISABLE_SINGLE
114
 
                                case DType.Single:
115
 
                                        return ReadSingle ();
116
 
#endif
117
 
 
118
 
                                case DType.Double:
119
 
                                        return ReadDouble ();
120
 
 
121
 
                                case DType.String:
122
 
                                        return ReadString ();
123
 
 
124
 
                                case DType.ObjectPath:
125
 
                                        return ReadObjectPath ();
126
 
 
127
 
                                case DType.Signature:
128
 
                                        return ReadSignature ();
129
 
 
130
 
                                case DType.Variant:
131
 
                                        return ReadVariant ();
132
 
 
133
 
                                default:
134
 
                                        throw new Exception ("Unhandled D-Bus type: " + dtype);
135
 
                        }
136
 
                }
137
 
 
138
 
                public object GetObject (Type type)
139
 
                {
140
 
                        ObjectPath path = ReadObjectPath ();
141
 
 
142
 
                        return message.Connection.GetObject (type, (string)message.Header[FieldCode.Sender], path);
143
 
                }
144
 
 
145
 
                public byte ReadByte ()
146
 
                {
147
 
                        return data[pos++];
148
 
                }
149
 
 
150
 
                public bool ReadBoolean ()
151
 
                {
152
 
                        uint intval = ReadUInt32 ();
153
 
 
154
 
                        switch (intval) {
155
 
                                case 0:
156
 
                                        return false;
157
 
                                case 1:
158
 
                                        return true;
159
 
                                default:
160
 
                                        throw new Exception ("Read value " + intval + " at position " + pos + " while expecting boolean (0/1)");
161
 
                        }
162
 
                }
163
 
 
164
 
                unsafe protected void MarshalUShort (void* dstPtr)
165
 
                {
166
 
                        ReadPad (2);
167
 
 
168
 
                        if (data.Length < pos + 2)
169
 
                                throw new Exception ("Cannot read beyond end of data");
170
 
 
171
 
                        if (endianness == Connection.NativeEndianness) {
172
 
                                fixed (byte* p = &data[pos])
173
 
                                        *((ushort*)dstPtr) = *((ushort*)p);
174
 
                        } else {
175
 
                                byte* dst = (byte*)dstPtr;
176
 
                                dst[0] = data[pos + 1];
177
 
                                dst[1] = data[pos + 0];
178
 
                        }
179
 
 
180
 
                        pos += 2;
181
 
                }
182
 
 
183
 
                unsafe public short ReadInt16 ()
184
 
                {
185
 
                        short val;
186
 
 
187
 
                        MarshalUShort (&val);
188
 
 
189
 
                        return val;
190
 
                }
191
 
 
192
 
                unsafe public ushort ReadUInt16 ()
193
 
                {
194
 
                        ushort val;
195
 
 
196
 
                        MarshalUShort (&val);
197
 
 
198
 
                        return val;
199
 
                }
200
 
 
201
 
                unsafe protected void MarshalUInt (void* dstPtr)
202
 
                {
203
 
                        ReadPad (4);
204
 
 
205
 
                        if (data.Length < pos + 4)
206
 
                                throw new Exception ("Cannot read beyond end of data");
207
 
 
208
 
                        if (endianness == Connection.NativeEndianness) {
209
 
                                fixed (byte* p = &data[pos])
210
 
                                        *((uint*)dstPtr) = *((uint*)p);
211
 
                        } else {
212
 
                                byte* dst = (byte*)dstPtr;
213
 
                                dst[0] = data[pos + 3];
214
 
                                dst[1] = data[pos + 2];
215
 
                                dst[2] = data[pos + 1];
216
 
                                dst[3] = data[pos + 0];
217
 
                        }
218
 
 
219
 
                        pos += 4;
220
 
                }
221
 
 
222
 
                unsafe public int ReadInt32 ()
223
 
                {
224
 
                        int val;
225
 
 
226
 
                        MarshalUInt (&val);
227
 
 
228
 
                        return val;
229
 
                }
230
 
 
231
 
                unsafe public uint ReadUInt32 ()
232
 
                {
233
 
                        uint val;
234
 
 
235
 
                        MarshalUInt (&val);
236
 
 
237
 
                        return val;
238
 
                }
239
 
 
240
 
                unsafe protected void MarshalULong (void* dstPtr)
241
 
                {
242
 
                        ReadPad (8);
243
 
 
244
 
                        if (data.Length < pos + 8)
245
 
                                throw new Exception ("Cannot read beyond end of data");
246
 
 
247
 
                        if (endianness == Connection.NativeEndianness) {
248
 
                                fixed (byte* p = &data[pos])
249
 
                                        *((ulong*)dstPtr) = *((ulong*)p);
250
 
                        } else {
251
 
                                byte* dst = (byte*)dstPtr;
252
 
                                for (int i = 0; i < 8; ++i)
253
 
                                        dst[i] = data[pos + (7 - i)];
254
 
                        }
255
 
 
256
 
                        pos += 8;
257
 
                }
258
 
 
259
 
                unsafe public long ReadInt64 ()
260
 
                {
261
 
                        long val;
262
 
 
263
 
                        MarshalULong (&val);
264
 
 
265
 
                        return val;
266
 
                }
267
 
 
268
 
                unsafe public ulong ReadUInt64 ()
269
 
                {
270
 
                        ulong val;
271
 
 
272
 
                        MarshalULong (&val);
273
 
 
274
 
                        return val;
275
 
                }
276
 
 
277
 
#if !DISABLE_SINGLE
278
 
                unsafe public float ReadSingle ()
279
 
                {
280
 
                        float val;
281
 
 
282
 
                        MarshalUInt (&val);
283
 
 
284
 
                        return val;
285
 
                }
286
 
#endif
287
 
 
288
 
                unsafe public double ReadDouble ()
289
 
                {
290
 
                        double val;
291
 
 
292
 
                        MarshalULong (&val);
293
 
 
294
 
                        return val;
295
 
                }
296
 
 
297
 
                public string ReadString ()
298
 
                {
299
 
                        uint ln = ReadUInt32 ();
300
 
 
301
 
                        string val = Encoding.UTF8.GetString (data, pos, (int)ln);
302
 
                        pos += (int)ln;
303
 
                        ReadNull ();
304
 
 
305
 
                        return val;
306
 
                }
307
 
 
308
 
                public ObjectPath ReadObjectPath ()
309
 
                {
310
 
                        //exactly the same as string
311
 
                        return new ObjectPath (ReadString ());
312
 
                }
313
 
 
314
 
                public Signature ReadSignature ()
315
 
                {
316
 
                        byte ln = ReadByte ();
317
 
 
318
 
                        // Avoid an array allocation for small signatures
319
 
                        if (ln == 1) {
320
 
                                DType dtype = (DType)ReadByte ();
321
 
                                ReadNull ();
322
 
                                return new Signature (dtype);
323
 
                        }
324
 
 
325
 
                        if (ln > Protocol.MaxSignatureLength)
326
 
                                throw new Exception ("Signature length " + ln + " exceeds maximum allowed " + Protocol.MaxSignatureLength + " bytes");
327
 
 
328
 
                        byte[] sigData = new byte[ln];
329
 
                        Array.Copy (data, pos, sigData, 0, (int)ln);
330
 
                        pos += (int)ln;
331
 
                        ReadNull ();
332
 
 
333
 
                        return Signature.Take (sigData);
334
 
                }
335
 
 
336
 
                public object ReadVariant ()
337
 
                {
338
 
                        return ReadValue (ReadSignature ());
339
 
                }
340
 
 
341
 
                // Used primarily for reading variant values
342
 
                object ReadValue (Signature sig)
343
 
                {
344
 
                        if (sig.IsPrimitive)
345
 
                                return ReadValue (sig[0]);
346
 
 
347
 
                        Type t = null;
348
 
                        try {
349
 
                                t = sig.ToType ();
350
 
                        } catch (NotSupportedException e) {
351
 
                                // We don't catch other exceptions as they indicate a malformed signature
352
 
                                if (Protocol.Verbose)
353
 
                                        Console.Error.WriteLine (e.Message);
354
 
                        }
355
 
 
356
 
                        /*
357
 
                        if (t == null) {
358
 
                                StepOver (sig);
359
 
                                return null;
360
 
                        }
361
 
                        */
362
 
 
363
 
                        if (t == null) {
364
 
                                ReadPad (sig.Alignment);
365
 
                                int startPos = pos;
366
 
                                StepOver (sig);
367
 
                                int ln = pos - startPos;
368
 
 
369
 
                                DValue dv = new DValue();
370
 
                                dv.endianness = endianness;
371
 
                                dv.signature = sig;
372
 
                                dv.data = new byte[ln];
373
 
                                Array.Copy (data, startPos, dv.data, 0, ln);
374
 
                                return dv;
375
 
                        }
376
 
 
377
 
                        return ReadValue (t);
378
 
                }
379
 
 
380
 
                //not pretty or efficient but works
381
 
                public void GetValueToDict (Type keyType, Type valType, System.Collections.IDictionary val)
382
 
                {
383
 
                        uint ln = ReadUInt32 ();
384
 
 
385
 
                        if (ln > Protocol.MaxArrayLength)
386
 
                                throw new Exception ("Dict length " + ln + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes");
387
 
 
388
 
                        //advance to the alignment of the element
389
 
                        //ReadPad (Protocol.GetAlignment (Signature.TypeToDType (type)));
390
 
                        ReadPad (8);
391
 
 
392
 
                        int endPos = pos + (int)ln;
393
 
 
394
 
                        //while (stream.Position != endPos)
395
 
                        while (pos < endPos)
396
 
                        {
397
 
                                ReadPad (8);
398
 
 
399
 
                                val.Add (ReadValue (keyType), ReadValue (valType));
400
 
                        }
401
 
 
402
 
                        if (pos != endPos)
403
 
                                throw new Exception ("Read pos " + pos + " != ep " + endPos);
404
 
                }
405
 
 
406
 
                //this could be made generic to avoid boxing
407
 
                public Array ReadArray (Type elemType)
408
 
                {
409
 
                        uint ln = ReadUInt32 ();
410
 
 
411
 
                        if (ln > Protocol.MaxArrayLength)
412
 
                                throw new Exception ("Array length " + ln + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes");
413
 
 
414
 
                        //TODO: more fast paths for primitive arrays
415
 
                        if (elemType == typeof (byte)) {
416
 
                                byte[] valb = new byte[ln];
417
 
                                Array.Copy (data, pos, valb, 0, (int)ln);
418
 
                                pos += (int)ln;
419
 
                                return valb;
420
 
                        }
421
 
 
422
 
                        //advance to the alignment of the element
423
 
                        ReadPad (Protocol.GetAlignment (Signature.TypeToDType (elemType)));
424
 
 
425
 
                        int endPos = pos + (int)ln;
426
 
 
427
 
                        //List<T> vals = new List<T> ();
428
 
                        System.Collections.ArrayList vals = new System.Collections.ArrayList ();
429
 
 
430
 
                        //while (stream.Position != endPos)
431
 
                        while (pos < endPos)
432
 
                                vals.Add (ReadValue (elemType));
433
 
 
434
 
                        if (pos != endPos)
435
 
                                throw new Exception ("Read pos " + pos + " != ep " + endPos);
436
 
 
437
 
                        return vals.ToArray (elemType);
438
 
                }
439
 
 
440
 
                //struct
441
 
                //probably the wrong place for this
442
 
                //there might be more elegant solutions
443
 
                public object ReadStruct (Type type)
444
 
                {
445
 
                        ReadPad (8);
446
 
 
447
 
                        object val = Activator.CreateInstance (type);
448
 
 
449
 
                        /*
450
 
                        if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (KeyValuePair<,>)) {
451
 
                                object elem;
452
 
 
453
 
                                System.Reflection.PropertyInfo key_prop = type.GetProperty ("Key");
454
 
                                GetValue (key_prop.PropertyType, out elem);
455
 
                                key_prop.SetValue (val, elem, null);
456
 
 
457
 
                                System.Reflection.PropertyInfo val_prop = type.GetProperty ("Value");
458
 
                                GetValue (val_prop.PropertyType, out elem);
459
 
                                val_prop.SetValue (val, elem, null);
460
 
 
461
 
                                return;
462
 
                        }
463
 
                        */
464
 
 
465
 
                        FieldInfo[] fis = type.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
466
 
 
467
 
                        foreach (System.Reflection.FieldInfo fi in fis)
468
 
                                fi.SetValue (val, ReadValue (fi.FieldType));
469
 
 
470
 
                        return val;
471
 
                }
472
 
 
473
 
                public void ReadNull ()
474
 
                {
475
 
                        if (data[pos] != 0)
476
 
                                throw new Exception ("Read non-zero byte at position " + pos + " while expecting null terminator");
477
 
                        pos++;
478
 
                }
479
 
 
480
 
                /*
481
 
                public void ReadPad (int alignment)
482
 
                {
483
 
                        pos = Protocol.Padded (pos, alignment);
484
 
                }
485
 
                */
486
 
 
487
 
                public void ReadPad (int alignment)
488
 
                {
489
 
                        for (int endPos = Protocol.Padded (pos, alignment) ; pos != endPos ; pos++)
490
 
                                if (data[pos] != 0)
491
 
                                        throw new Exception ("Read non-zero byte at position " + pos + " while expecting padding");
492
 
                }
493
 
        }
494
 
}