~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/MessageWriter.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
 
using System.Runtime.InteropServices;
11
 
 
12
 
namespace NDesk.DBus
13
 
{
14
 
        sealed class MessageWriter
15
 
        {
16
 
                EndianFlag endianness;
17
 
                internal MemoryStream stream;
18
 
 
19
 
                public Connection connection;
20
 
 
21
 
                //a default constructor is a bad idea for now as we want to make sure the header and content-type match
22
 
                public MessageWriter () : this (Connection.NativeEndianness) {}
23
 
 
24
 
                public MessageWriter (EndianFlag endianness)
25
 
                {
26
 
                        this.endianness = endianness;
27
 
                        stream = new MemoryStream ();
28
 
                }
29
 
 
30
 
                public byte[] ToArray ()
31
 
                {
32
 
                        //TODO: mark the writer locked or something here
33
 
                        return stream.ToArray ();
34
 
                }
35
 
 
36
 
                public void ToStream (Stream dest)
37
 
                {
38
 
                        stream.WriteTo (dest);
39
 
                }
40
 
 
41
 
                public void CloseWrite ()
42
 
                {
43
 
                        WritePad (8);
44
 
                }
45
 
 
46
 
                public void Write (byte val)
47
 
                {
48
 
                        stream.WriteByte (val);
49
 
                }
50
 
 
51
 
                public void Write (bool val)
52
 
                {
53
 
                        Write ((uint) (val ? 1 : 0));
54
 
                }
55
 
 
56
 
                // Buffer for integer marshaling
57
 
                byte[] dst = new byte[8];
58
 
                unsafe void MarshalUShort (void* dataPtr)
59
 
                {
60
 
                        WritePad (2);
61
 
 
62
 
                        if (endianness == Connection.NativeEndianness) {
63
 
                                fixed (byte* p = &dst[0])
64
 
                                        *((ushort*)p) = *((ushort*)dataPtr);
65
 
                        } else {
66
 
                                byte* data = (byte*)dataPtr;
67
 
                                dst[0] = data[1];
68
 
                                dst[1] = data[0];
69
 
                        }
70
 
 
71
 
                        stream.Write (dst, 0, 2);
72
 
                }
73
 
 
74
 
                unsafe public void Write (short val)
75
 
                {
76
 
                        MarshalUShort (&val);
77
 
                }
78
 
 
79
 
                unsafe public void Write (ushort val)
80
 
                {
81
 
                        MarshalUShort (&val);
82
 
                }
83
 
 
84
 
                unsafe void MarshalUInt (void* dataPtr)
85
 
                {
86
 
                        WritePad (4);
87
 
 
88
 
                        if (endianness == Connection.NativeEndianness) {
89
 
                                fixed (byte* p = &dst[0])
90
 
                                        *((uint*)p) = *((uint*)dataPtr);
91
 
                        } else {
92
 
                                byte* data = (byte*)dataPtr;
93
 
                                dst[0] = data[3];
94
 
                                dst[1] = data[2];
95
 
                                dst[2] = data[1];
96
 
                                dst[3] = data[0];
97
 
                        }
98
 
 
99
 
                        stream.Write (dst, 0, 4);
100
 
                }
101
 
 
102
 
                unsafe public void Write (int val)
103
 
                {
104
 
                        MarshalUInt (&val);
105
 
                }
106
 
 
107
 
                unsafe public void Write (uint val)
108
 
                {
109
 
                        MarshalUInt (&val);
110
 
                }
111
 
 
112
 
                unsafe void MarshalULong (void* dataPtr)
113
 
                {
114
 
                        WritePad (8);
115
 
 
116
 
                        if (endianness == Connection.NativeEndianness) {
117
 
                                fixed (byte* p = &dst[0])
118
 
                                        *((ulong*)p) = *((ulong*)dataPtr);
119
 
                        } else {
120
 
                                byte* data = (byte*)dataPtr;
121
 
                                for (int i = 0; i < 8; ++i)
122
 
                                        dst[i] = data[7 - i];
123
 
                        }
124
 
 
125
 
                        stream.Write (dst, 0, 8);
126
 
                }
127
 
 
128
 
                unsafe public void Write (long val)
129
 
                {
130
 
                        MarshalULong (&val);
131
 
                }
132
 
 
133
 
                unsafe public void Write (ulong val)
134
 
                {
135
 
                        MarshalULong (&val);
136
 
                }
137
 
 
138
 
#if !DISABLE_SINGLE
139
 
                unsafe public void Write (float val)
140
 
                {
141
 
                        MarshalUInt (&val);
142
 
                }
143
 
#endif
144
 
 
145
 
                unsafe public void Write (double val)
146
 
                {
147
 
                        MarshalULong (&val);
148
 
                }
149
 
 
150
 
                public void Write (string val)
151
 
                {
152
 
                        byte[] utf8_data = Encoding.UTF8.GetBytes (val);
153
 
                        Write ((uint)utf8_data.Length);
154
 
                        stream.Write (utf8_data, 0, utf8_data.Length);
155
 
                        WriteNull ();
156
 
                }
157
 
 
158
 
                public void Write (ObjectPath val)
159
 
                {
160
 
                        Write (val.Value);
161
 
                }
162
 
 
163
 
                public void Write (Signature val)
164
 
                {
165
 
                        byte[] ascii_data = val.GetBuffer ();
166
 
 
167
 
                        if (ascii_data.Length > Protocol.MaxSignatureLength)
168
 
                                throw new Exception ("Signature length " + ascii_data.Length + " exceeds maximum allowed " + Protocol.MaxSignatureLength + " bytes");
169
 
 
170
 
                        Write ((byte)ascii_data.Length);
171
 
                        stream.Write (ascii_data, 0, ascii_data.Length);
172
 
                        WriteNull ();
173
 
                }
174
 
 
175
 
                [Obsolete]
176
 
                public void WriteComplex (object val, Type type)
177
 
                {
178
 
                        if (type == typeof (void))
179
 
                                return;
180
 
 
181
 
                        if (type.IsArray) {
182
 
                                MethodInfo miDict = typeof (MessageWriter).GetMethod ("WriteArray");
183
 
                                MethodInfo mi = miDict.MakeGenericMethod (type.GetElementType ());
184
 
                                mi.Invoke (this, new object[] {val});
185
 
                        } else if (type.IsGenericType && (type.GetGenericTypeDefinition () == typeof (IDictionary<,>) || type.GetGenericTypeDefinition () == typeof (Dictionary<,>))) {
186
 
                                Type[] genArgs = type.GetGenericArguments ();
187
 
                                MethodInfo miDict = typeof (MessageWriter).GetMethod ("WriteFromDict");
188
 
                                MethodInfo mi = miDict.MakeGenericMethod (genArgs);
189
 
                                mi.Invoke (this, new object[] {val});
190
 
                        } else if (Mapper.IsPublic (type)) {
191
 
                                WriteObject (type, val);
192
 
                        } else if (!type.IsPrimitive && !type.IsEnum) {
193
 
                                WriteValueType (val, type);
194
 
                                /*
195
 
                        } else if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (Nullable<>)) {
196
 
                                //is it possible to support nullable types?
197
 
                                Type[] genArgs = type.GetGenericArguments ();
198
 
                                WriteVariant (genArgs[0], val);
199
 
                                */
200
 
                        } else {
201
 
                                throw new Exception ("Can't write");
202
 
                        }
203
 
                }
204
 
 
205
 
                [Obsolete]
206
 
                public void Write (Type type, object val)
207
 
                {
208
 
                        if (type == typeof (void))
209
 
                                return;
210
 
 
211
 
                        if (type.IsArray) {
212
 
                                MethodInfo miDict = typeof (MessageWriter).GetMethod ("WriteArray");
213
 
                                MethodInfo mi = miDict.MakeGenericMethod (type.GetElementType ());
214
 
                                mi.Invoke (this, new object[] {val});
215
 
                        } else if (type == typeof (ObjectPath)) {
216
 
                                Write ((ObjectPath)val);
217
 
                        } else if (type == typeof (Signature)) {
218
 
                                Write ((Signature)val);
219
 
                        } else if (type == typeof (object)) {
220
 
                                Write (val);
221
 
                        } else if (type == typeof (string)) {
222
 
                                Write ((string)val);
223
 
                        } else if (type.IsGenericType && (type.GetGenericTypeDefinition () == typeof (IDictionary<,>) || type.GetGenericTypeDefinition () == typeof (Dictionary<,>))) {
224
 
                                Type[] genArgs = type.GetGenericArguments ();
225
 
                                MethodInfo miDict = typeof (MessageWriter).GetMethod ("WriteFromDict");
226
 
                                MethodInfo mi = miDict.MakeGenericMethod (genArgs);
227
 
                                mi.Invoke (this, new object[] {val});
228
 
                        } else if (Mapper.IsPublic (type)) {
229
 
                                WriteObject (type, val);
230
 
                        } else if (!type.IsPrimitive && !type.IsEnum) {
231
 
                                WriteValueType (val, type);
232
 
                        } else {
233
 
                                Write (Signature.TypeToDType (type), val);
234
 
                        }
235
 
                }
236
 
 
237
 
                //helper method, should not be used as it boxes needlessly
238
 
                public void Write (DType dtype, object val)
239
 
                {
240
 
                        switch (dtype)
241
 
                        {
242
 
                                case DType.Byte:
243
 
                                {
244
 
                                        Write ((byte)val);
245
 
                                }
246
 
                                break;
247
 
                                case DType.Boolean:
248
 
                                {
249
 
                                        Write ((bool)val);
250
 
                                }
251
 
                                break;
252
 
                                case DType.Int16:
253
 
                                {
254
 
                                        Write ((short)val);
255
 
                                }
256
 
                                break;
257
 
                                case DType.UInt16:
258
 
                                {
259
 
                                        Write ((ushort)val);
260
 
                                }
261
 
                                break;
262
 
                                case DType.Int32:
263
 
                                {
264
 
                                        Write ((int)val);
265
 
                                }
266
 
                                break;
267
 
                                case DType.UInt32:
268
 
                                {
269
 
                                        Write ((uint)val);
270
 
                                }
271
 
                                break;
272
 
                                case DType.Int64:
273
 
                                {
274
 
                                        Write ((long)val);
275
 
                                }
276
 
                                break;
277
 
                                case DType.UInt64:
278
 
                                {
279
 
                                        Write ((ulong)val);
280
 
                                }
281
 
                                break;
282
 
#if !DISABLE_SINGLE
283
 
                                case DType.Single:
284
 
                                {
285
 
                                        Write ((float)val);
286
 
                                }
287
 
                                break;
288
 
#endif
289
 
                                case DType.Double:
290
 
                                {
291
 
                                        Write ((double)val);
292
 
                                }
293
 
                                break;
294
 
                                case DType.String:
295
 
                                {
296
 
                                        Write ((string)val);
297
 
                                }
298
 
                                break;
299
 
                                case DType.ObjectPath:
300
 
                                {
301
 
                                        Write ((ObjectPath)val);
302
 
                                }
303
 
                                break;
304
 
                                case DType.Signature:
305
 
                                {
306
 
                                        Write ((Signature)val);
307
 
                                }
308
 
                                break;
309
 
                                case DType.Variant:
310
 
                                {
311
 
                                        Write ((object)val);
312
 
                                }
313
 
                                break;
314
 
                                default:
315
 
                                throw new Exception ("Unhandled D-Bus type: " + dtype);
316
 
                        }
317
 
                }
318
 
 
319
 
                public void WriteObject (Type type, object val)
320
 
                {
321
 
                        ObjectPath path;
322
 
 
323
 
                        BusObject bobj = val as BusObject;
324
 
 
325
 
                        if (bobj == null && val is MarshalByRefObject) {
326
 
                                bobj = ((MarshalByRefObject)val).GetLifetimeService () as BusObject;
327
 
                        }
328
 
 
329
 
                        if (bobj == null)
330
 
                                throw new Exception ("No object reference to write");
331
 
 
332
 
                        path = bobj.Path;
333
 
 
334
 
                        Write (path);
335
 
                }
336
 
 
337
 
                //variant
338
 
                public void Write (object val)
339
 
                {
340
 
                        if (val == null)
341
 
                                throw new NotSupportedException ("Cannot send null variant");
342
 
 
343
 
                        if (val is DValue) {
344
 
                                DValue dv = (DValue)val;
345
 
 
346
 
                                if (dv.endianness != endianness)
347
 
                                        throw new NotImplementedException ("Writing opposite endian DValues not yet implemented.");
348
 
 
349
 
                                Write (dv.signature);
350
 
                                WritePad (dv.signature.Alignment);
351
 
                                stream.Write (dv.data, 0, dv.data.Length);
352
 
                                return;
353
 
                        }
354
 
 
355
 
                        Type type = val.GetType ();
356
 
 
357
 
                        WriteVariant (type, val);
358
 
                }
359
 
 
360
 
                public void WriteVariant (Type type, object val)
361
 
                {
362
 
                        Signature sig = Signature.GetSig (type);
363
 
 
364
 
                        Write (sig);
365
 
                        Write (type, val);
366
 
                }
367
 
 
368
 
                //this requires a seekable stream for now
369
 
                public unsafe void WriteArray<T> (T[] val)
370
 
                {
371
 
                        Type elemType = typeof (T);
372
 
 
373
 
                        if (elemType == typeof (byte)) {
374
 
                                if (val.Length > Protocol.MaxArrayLength)
375
 
                                        throw new Exception ("Array length " + val.Length + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes");
376
 
 
377
 
                                Write ((uint)val.Length);
378
 
                                stream.Write ((byte[])(object)val, 0, val.Length);
379
 
                                return;
380
 
                        }
381
 
 
382
 
                        if (elemType.IsEnum)
383
 
                                elemType = Enum.GetUnderlyingType (elemType);
384
 
 
385
 
                        Signature sigElem = Signature.GetSig (elemType);
386
 
                        int fixedSize = 0;
387
 
                        if (endianness == Connection.NativeEndianness && elemType.IsValueType && !sigElem.IsStruct && sigElem.GetFixedSize (ref fixedSize)) {
388
 
                                int byteLength = fixedSize * val.Length;
389
 
                                if (byteLength > Protocol.MaxArrayLength)
390
 
                                        throw new Exception ("Array length " + byteLength + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes");
391
 
                                Write ((uint)byteLength);
392
 
                                WritePad (sigElem.Alignment);
393
 
 
394
 
                                GCHandle valHandle = GCHandle.Alloc (val, GCHandleType.Pinned);
395
 
                                IntPtr p = valHandle.AddrOfPinnedObject ();
396
 
                                byte[] data = new byte[byteLength];
397
 
                                byte* bp = (byte*)p;
398
 
                                for (int i = 0 ; i != byteLength ; i++)
399
 
                                        data[i] = bp[i];
400
 
                                stream.Write (data, 0, data.Length);
401
 
                                valHandle.Free ();
402
 
                                return;
403
 
                        }
404
 
 
405
 
                        long origPos = stream.Position;
406
 
                        Write ((uint)0);
407
 
 
408
 
                        //advance to the alignment of the element
409
 
                        WritePad (sigElem.Alignment);
410
 
 
411
 
                        long startPos = stream.Position;
412
 
 
413
 
                        TypeWriter<T> tWriter = TypeImplementer.GetTypeWriter<T> ();
414
 
 
415
 
                        foreach (T elem in val)
416
 
                                tWriter (this, elem);
417
 
 
418
 
                        long endPos = stream.Position;
419
 
                        uint ln = (uint)(endPos - startPos);
420
 
                        stream.Position = origPos;
421
 
 
422
 
                        if (ln > Protocol.MaxArrayLength)
423
 
                                throw new Exception ("Array length " + ln + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes");
424
 
 
425
 
                        Write (ln);
426
 
                        stream.Position = endPos;
427
 
                }
428
 
 
429
 
                public void WriteValueType (object val, Type type)
430
 
                {
431
 
                        MethodInfo mi = TypeImplementer.GetWriteMethod (type);
432
 
                        mi.Invoke (null, new object[] {this, val});
433
 
                }
434
 
 
435
 
                public void WriteStructure<T> (T value)
436
 
                {
437
 
                        TypeWriter<T> tWriter = TypeImplementer.GetTypeWriter<T> ();
438
 
                        tWriter (this, value);
439
 
                }
440
 
 
441
 
                public void WriteFromDict<TKey,TValue> (IDictionary<TKey,TValue> val)
442
 
                {
443
 
                        long origPos = stream.Position;
444
 
                        Write ((uint)0);
445
 
 
446
 
                        WritePad (8);
447
 
 
448
 
                        long startPos = stream.Position;
449
 
 
450
 
                        TypeWriter<TKey> keyWriter = TypeImplementer.GetTypeWriter<TKey> ();
451
 
                        TypeWriter<TValue> valueWriter = TypeImplementer.GetTypeWriter<TValue> ();
452
 
 
453
 
                        foreach (KeyValuePair<TKey,TValue> entry in val)
454
 
                        {
455
 
                                WritePad (8);
456
 
                                keyWriter (this, entry.Key);
457
 
                                valueWriter (this, entry.Value);
458
 
                        }
459
 
 
460
 
                        long endPos = stream.Position;
461
 
                        uint ln = (uint)(endPos - startPos);
462
 
                        stream.Position = origPos;
463
 
 
464
 
                        if (ln > Protocol.MaxArrayLength)
465
 
                                throw new Exception ("Dict length " + ln + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes");
466
 
 
467
 
                        Write (ln);
468
 
                        stream.Position = endPos;
469
 
                }
470
 
 
471
 
                /*
472
 
                public void Write (IDictionary<FieldCode, object> val)
473
 
                {
474
 
                        WriteHeaderDict(val);
475
 
                }
476
 
 
477
 
                public void Write (Dictionary<FieldCode, object> val)
478
 
                {
479
 
                        WriteHeaderDict (val);
480
 
                }
481
 
                */
482
 
                
483
 
                /*
484
 
                public void Write (Dictionary<byte, object> val)
485
 
                {
486
 
                        long origPos = stream.Position;
487
 
                        Write ((uint)0);
488
 
 
489
 
                        WritePad (8);
490
 
 
491
 
                        long startPos = stream.Position;
492
 
 
493
 
                        foreach (KeyValuePair<byte, object> entry in val) {
494
 
                                WritePad (8);
495
 
                                Write (entry.Key);
496
 
                                Write (entry.Value);
497
 
                        }
498
 
 
499
 
                        long endPos = stream.Position;
500
 
                        uint ln = (uint)(endPos - startPos);
501
 
                        stream.Position = origPos;
502
 
 
503
 
                        if (ln > Protocol.MaxArrayLength)
504
 
                                throw new Exception ("Dict length " + ln + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes");
505
 
 
506
 
                        Write (ln);
507
 
                        stream.Position = endPos;
508
 
                }
509
 
                */
510
 
 
511
 
                internal void WriteHeaderFields (Dictionary<byte, object> val)
512
 
                {
513
 
                        long origPos = stream.Position;
514
 
                        Write ((uint)0);
515
 
 
516
 
                        WritePad (8);
517
 
 
518
 
                        long startPos = stream.Position;
519
 
 
520
 
                        foreach (KeyValuePair<byte, object> entry in val) {
521
 
                                WritePad (8);
522
 
                                Write (entry.Key);
523
 
                                switch ((FieldCode)entry.Key) {
524
 
                                        case FieldCode.Destination:
525
 
                                        case FieldCode.ErrorName:
526
 
                                        case FieldCode.Interface:
527
 
                                        case FieldCode.Member:
528
 
                                        case FieldCode.Sender:
529
 
                                                Write (Signature.StringSig);
530
 
                                                Write ((string)entry.Value);
531
 
                                                break;
532
 
                                        case FieldCode.Path:
533
 
                                                Write (Signature.ObjectPathSig);
534
 
                                                Write ((ObjectPath)entry.Value);
535
 
                                                break;
536
 
                                        case FieldCode.ReplySerial:
537
 
                                                Write (Signature.UInt32Sig);
538
 
                                                Write ((uint)entry.Value);
539
 
                                                break;
540
 
                                        default:
541
 
                                                Write (entry.Value);
542
 
                                                break;
543
 
                                }
544
 
                        }
545
 
 
546
 
                        long endPos = stream.Position;
547
 
                        uint ln = (uint)(endPos - startPos);
548
 
                        stream.Position = origPos;
549
 
 
550
 
                        if (ln > Protocol.MaxArrayLength)
551
 
                                throw new Exception ("Dict length " + ln + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes");
552
 
 
553
 
                        Write (ln);
554
 
                        stream.Position = endPos;
555
 
                }
556
 
 
557
 
                public void WriteNull ()
558
 
                {
559
 
                        stream.WriteByte (0);
560
 
                }
561
 
 
562
 
                // Source buffer for zero-padding
563
 
                static readonly byte[] nullBytes = new byte[8];
564
 
                public void WritePad (int alignment)
565
 
                {
566
 
                        int needed = Protocol.PadNeeded ((int)stream.Position, alignment);
567
 
                        stream.Write (nullBytes, 0, needed);
568
 
                }
569
 
        }
570
 
}