~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/Signature.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
 
 
8
 
using System.Collections.Generic;
9
 
//TODO: Reflection should be done at a higher level than this class
10
 
using System.Reflection;
11
 
 
12
 
namespace NDesk.DBus
13
 
{
14
 
        //maybe this should be nullable?
15
 
        struct Signature
16
 
        {
17
 
                //TODO: this class needs some work
18
 
                //Data should probably include the null terminator
19
 
 
20
 
                public static readonly Signature Empty = new Signature (String.Empty);
21
 
                public static readonly Signature ByteSig = Allocate (DType.Byte);
22
 
                public static readonly Signature UInt16Sig = Allocate (DType.UInt16);
23
 
                public static readonly Signature UInt32Sig = Allocate (DType.UInt32);
24
 
                public static readonly Signature StringSig = Allocate (DType.String);
25
 
                public static readonly Signature ObjectPathSig = Allocate (DType.ObjectPath);
26
 
                public static readonly Signature SignatureSig = Allocate (DType.Signature);
27
 
                public static readonly Signature VariantSig = Allocate (DType.Variant);
28
 
 
29
 
                public static bool operator == (Signature a, Signature b)
30
 
                {
31
 
                        if (a.data == b.data)
32
 
                                return true;
33
 
 
34
 
                        if (a.data == null)
35
 
                                return false;
36
 
 
37
 
                        if (b.data == null)
38
 
                                return false;
39
 
 
40
 
                        if (a.data.Length != b.data.Length)
41
 
                                return false;
42
 
 
43
 
                        for (int i = 0 ; i != a.data.Length ; i++)
44
 
                                if (a.data[i] != b.data[i])
45
 
                                        return false;
46
 
 
47
 
                        return true;
48
 
                }
49
 
 
50
 
                public static bool operator != (Signature a, Signature b)
51
 
                {
52
 
                        return !(a == b);
53
 
                }
54
 
 
55
 
                public override bool Equals (object o)
56
 
                {
57
 
                        if (o == null)
58
 
                                return false;
59
 
 
60
 
                        if (!(o is Signature))
61
 
                                return false;
62
 
 
63
 
                        return this == (Signature)o;
64
 
                }
65
 
 
66
 
                public override int GetHashCode ()
67
 
                {
68
 
                        // TODO: Avoid string conversion
69
 
                        return Value.GetHashCode ();
70
 
                }
71
 
 
72
 
                public static Signature operator + (Signature s1, Signature s2)
73
 
                {
74
 
                        return Concat (s1, s2);
75
 
                }
76
 
 
77
 
                public static Signature Concat (Signature s1, Signature s2)
78
 
                {
79
 
                        if (s1.data == null && s2.data == null)
80
 
                                return Signature.Empty;
81
 
 
82
 
                        if (s1.data == null)
83
 
                                return s2;
84
 
 
85
 
                        if (s2.data == null)
86
 
                                return s1;
87
 
 
88
 
                        if (s1.Length + s2.Length == 0)
89
 
                                return Signature.Empty;
90
 
 
91
 
                        byte[] data = new byte[s1.data.Length + s2.data.Length];
92
 
                        s1.data.CopyTo (data, 0);
93
 
                        s2.data.CopyTo (data, s1.data.Length);
94
 
                        return Signature.Take (data);
95
 
                }
96
 
 
97
 
                public Signature (string value)
98
 
                {
99
 
                        if (value.Length == 0) {
100
 
                                this.data = Empty.data;
101
 
                                return;
102
 
                        }
103
 
 
104
 
                        if (value.Length == 1) {
105
 
                                this.data = DataForDType ((DType)value[0]);
106
 
                                return;
107
 
                        }
108
 
 
109
 
                        this.data = Encoding.ASCII.GetBytes (value);
110
 
                }
111
 
 
112
 
                internal static Signature Take (byte[] value)
113
 
                {
114
 
                        Signature sig;
115
 
 
116
 
                        if (value.Length == 0) {
117
 
                                sig.data = Empty.data;
118
 
                                return sig;
119
 
                        }
120
 
 
121
 
                        if (value.Length == 1) {
122
 
                                sig.data = DataForDType ((DType)value[0]);
123
 
                                return sig;
124
 
                        }
125
 
 
126
 
                        sig.data = value;
127
 
                        return sig;
128
 
                }
129
 
 
130
 
                static byte[] DataForDType (DType value)
131
 
                {
132
 
                        // Reduce heap allocations.
133
 
                        // For now, we only cache the most common protocol signatures.
134
 
                        switch (value) {
135
 
                                case DType.Byte:
136
 
                                        return ByteSig.data;
137
 
                                case DType.UInt16:
138
 
                                        return UInt16Sig.data;
139
 
                                case DType.UInt32:
140
 
                                        return UInt32Sig.data;
141
 
                                case DType.String:
142
 
                                        return StringSig.data;
143
 
                                case DType.ObjectPath:
144
 
                                        return ObjectPathSig.data;
145
 
                                case DType.Signature:
146
 
                                        return SignatureSig.data;
147
 
                                case DType.Variant:
148
 
                                        return VariantSig.data;
149
 
                                default:
150
 
                                        return new byte[] {(byte)value};
151
 
                        }
152
 
                }
153
 
 
154
 
                private static Signature Allocate (DType value)
155
 
                {
156
 
                        Signature sig;
157
 
                        sig.data = new byte[] {(byte)value};
158
 
                        return sig;
159
 
                }
160
 
 
161
 
                internal Signature (DType value)
162
 
                {
163
 
                        this.data = DataForDType (value);
164
 
                }
165
 
 
166
 
                internal Signature (DType[] value)
167
 
                {
168
 
                        if (value.Length == 0) {
169
 
                                this.data = Empty.data;
170
 
                                return;
171
 
                        }
172
 
 
173
 
                        if (value.Length == 1) {
174
 
                                this.data = DataForDType (value[0]);
175
 
                                return;
176
 
                        }
177
 
 
178
 
                        this.data = new byte[value.Length];
179
 
 
180
 
                        for (int i = 0 ; i != value.Length ; i++)
181
 
                                this.data[i] = (byte)value[i];
182
 
                }
183
 
 
184
 
                byte[] data;
185
 
 
186
 
                //TODO: this should be private, but MessageWriter and Monitor still use it
187
 
                //[Obsolete]
188
 
                public byte[] GetBuffer ()
189
 
                {
190
 
                        return data;
191
 
                }
192
 
 
193
 
                internal DType this[int index]
194
 
                {
195
 
                        get {
196
 
                                return (DType)data[index];
197
 
                        }
198
 
                }
199
 
 
200
 
                public int Length
201
 
                {
202
 
                        get {
203
 
                                return data.Length;
204
 
                        }
205
 
                }
206
 
 
207
 
                //[Obsolete]
208
 
                public string Value
209
 
                {
210
 
                        get {
211
 
                                //FIXME: hack to handle bad case when Data is null
212
 
                                if (data == null)
213
 
                                        return String.Empty;
214
 
 
215
 
                                return Encoding.ASCII.GetString (data);
216
 
                        }
217
 
                }
218
 
 
219
 
                public override string ToString ()
220
 
                {
221
 
                        return Value;
222
 
 
223
 
                        /*
224
 
                        StringBuilder sb = new StringBuilder ();
225
 
 
226
 
                        foreach (DType t in data) {
227
 
                                //we shouldn't rely on object mapping here, but it's an easy way to get string representations for now
228
 
                                Type type = DTypeToType (t);
229
 
                                if (type != null) {
230
 
                                        sb.Append (type.Name);
231
 
                                } else {
232
 
                                        char c = (char)t;
233
 
                                        if (!Char.IsControl (c))
234
 
                                                sb.Append (c);
235
 
                                        else
236
 
                                                sb.Append (@"\" + (int)c);
237
 
                                }
238
 
                                sb.Append (" ");
239
 
                        }
240
 
 
241
 
                        return sb.ToString ();
242
 
                        */
243
 
                }
244
 
 
245
 
                public Signature MakeArraySignature ()
246
 
                {
247
 
                        return new Signature (DType.Array) + this;
248
 
                }
249
 
 
250
 
                public static Signature MakeStruct (params Signature[] elems)
251
 
                {
252
 
                        Signature sig = Signature.Empty;
253
 
 
254
 
                        sig += new Signature (DType.StructBegin);
255
 
 
256
 
                        foreach (Signature elem in elems)
257
 
                                sig += elem;
258
 
 
259
 
                        sig += new Signature (DType.StructEnd);
260
 
 
261
 
                        return sig;
262
 
                }
263
 
 
264
 
                public static Signature MakeDictEntry (Signature keyType, Signature valueType)
265
 
                {
266
 
                        Signature sig = Signature.Empty;
267
 
 
268
 
                        sig += new Signature (DType.DictEntryBegin);
269
 
 
270
 
                        sig += keyType;
271
 
                        sig += valueType;
272
 
 
273
 
                        sig += new Signature (DType.DictEntryEnd);
274
 
 
275
 
                        return sig;
276
 
                }
277
 
 
278
 
                public static Signature MakeDict (Signature keyType, Signature valueType)
279
 
                {
280
 
                        return MakeDictEntry (keyType, valueType).MakeArraySignature ();
281
 
                }
282
 
 
283
 
                public int Alignment
284
 
                {
285
 
                        get {
286
 
                                if (data.Length == 0)
287
 
                                        return 0;
288
 
 
289
 
                                return Protocol.GetAlignment (this[0]);
290
 
                        }
291
 
                }
292
 
 
293
 
                static int GetSize (DType dtype)
294
 
                {
295
 
                        switch (dtype) {
296
 
                                case DType.Byte:
297
 
                                        return 1;
298
 
                                case DType.Boolean:
299
 
                                        return 4;
300
 
                                case DType.Int16:
301
 
                                case DType.UInt16:
302
 
                                        return 2;
303
 
                                case DType.Int32:
304
 
                                case DType.UInt32:
305
 
                                        return 4;
306
 
                                case DType.Int64:
307
 
                                case DType.UInt64:
308
 
                                        return 8;
309
 
#if !DISABLE_SINGLE
310
 
                                case DType.Single: //Not yet supported!
311
 
                                        return 4;
312
 
#endif
313
 
                                case DType.Double:
314
 
                                        return 8;
315
 
                                case DType.String:
316
 
                                case DType.ObjectPath:
317
 
                                case DType.Signature:
318
 
                                case DType.Array:
319
 
                                case DType.StructBegin:
320
 
                                case DType.Variant:
321
 
                                case DType.DictEntryBegin:
322
 
                                        return -1;
323
 
                                case DType.Invalid:
324
 
                                default:
325
 
                                        throw new Exception ("Cannot determine size of " + dtype);
326
 
                        }
327
 
                }
328
 
 
329
 
                public bool GetFixedSize (ref int size)
330
 
                {
331
 
                        if (size < 0)
332
 
                                return false;
333
 
 
334
 
                        if (data.Length == 0)
335
 
                                return true;
336
 
 
337
 
                        // Sensible?
338
 
                        size = Protocol.Padded (size, Alignment);
339
 
 
340
 
                        if (data.Length == 1) {
341
 
                                int valueSize = GetSize (this[0]);
342
 
 
343
 
                                if (valueSize == -1)
344
 
                                        return false;
345
 
 
346
 
                                size += valueSize;
347
 
                                return true;
348
 
                        }
349
 
 
350
 
                        if (IsStructlike) {
351
 
                                foreach (Signature sig in GetParts ())
352
 
                                                if (!sig.GetFixedSize (ref size))
353
 
                                                        return false;
354
 
                                return true;
355
 
                        }
356
 
 
357
 
                        if (IsArray || IsDict)
358
 
                                return false;
359
 
 
360
 
                        if (IsStruct) {
361
 
                                foreach (Signature sig in GetFieldSignatures ())
362
 
                                                if (!sig.GetFixedSize (ref size))
363
 
                                                        return false;
364
 
                                return true;
365
 
                        }
366
 
 
367
 
                        // Any other cases?
368
 
                        throw new Exception ();
369
 
                }
370
 
 
371
 
                public bool IsFixedSize
372
 
                {
373
 
                        get {
374
 
                                if (data.Length == 0)
375
 
                                        return true;
376
 
 
377
 
                                if (data.Length == 1) {
378
 
                                        int size = GetSize (this[0]);
379
 
                                        return size != -1;
380
 
                                }
381
 
 
382
 
                                if (IsStructlike) {
383
 
                                        foreach (Signature sig in GetParts ())
384
 
                                                if (!sig.IsFixedSize)
385
 
                                                        return false;
386
 
                                        return true;
387
 
                                }
388
 
 
389
 
                                if (IsArray || IsDict)
390
 
                                        return false;
391
 
 
392
 
                                if (IsStruct) {
393
 
                                        foreach (Signature sig in GetFieldSignatures ())
394
 
                                                if (!sig.IsFixedSize)
395
 
                                                        return false;
396
 
                                        return true;
397
 
                                }
398
 
 
399
 
                                // Any other cases?
400
 
                                throw new Exception ();
401
 
                        }
402
 
                }
403
 
 
404
 
                //TODO: complete this
405
 
                public bool IsPrimitive
406
 
                {
407
 
                        get {
408
 
                                if (data.Length != 1)
409
 
                                        return false;
410
 
 
411
 
                                if (this[0] == DType.Variant)
412
 
                                        return false;
413
 
 
414
 
                                if (this[0] == DType.Invalid)
415
 
                                        return false;
416
 
 
417
 
                                return true;
418
 
                        }
419
 
                }
420
 
 
421
 
                public bool IsStruct
422
 
                {
423
 
                        get {
424
 
                                if (Length < 2)
425
 
                                        return false;
426
 
 
427
 
                                if (this[0] != DType.StructBegin)
428
 
                                        return false;
429
 
 
430
 
                                // FIXME: Incorrect! What if this is in fact a Structlike starting and finishing with structs?
431
 
                                if (this[Length - 1] != DType.StructEnd)
432
 
                                        return false;
433
 
 
434
 
                                return true;
435
 
                        }
436
 
                }
437
 
 
438
 
                public bool IsDictEntry
439
 
                {
440
 
                        get {
441
 
                                if (Length < 2)
442
 
                                        return false;
443
 
 
444
 
                                if (this[0] != DType.DictEntryBegin)
445
 
                                        return false;
446
 
 
447
 
                                // FIXME: Incorrect! What if this is in fact a Structlike starting and finishing with structs?
448
 
                                if (this[Length - 1] != DType.DictEntryEnd)
449
 
                                        return false;
450
 
 
451
 
                                return true;
452
 
                        }
453
 
                }
454
 
 
455
 
                public bool IsStructlike
456
 
                {
457
 
                        get {
458
 
                                if (Length < 2)
459
 
                                        return false;
460
 
 
461
 
                                if (IsArray)
462
 
                                        return false;
463
 
 
464
 
                                if (IsDict)
465
 
                                        return false;
466
 
 
467
 
                                if (IsStruct)
468
 
                                        return false;
469
 
 
470
 
                                return true;
471
 
                        }
472
 
                }
473
 
 
474
 
                public bool IsDict
475
 
                {
476
 
                        get {
477
 
                                if (Length < 3)
478
 
                                        return false;
479
 
 
480
 
                                if (!IsArray)
481
 
                                        return false;
482
 
 
483
 
                                // 0 is 'a'
484
 
                                if (this[1] != DType.DictEntryBegin)
485
 
                                        return false;
486
 
 
487
 
                                return true;
488
 
                        }
489
 
                }
490
 
 
491
 
                public bool IsArray
492
 
                {
493
 
                        get {
494
 
                                if (Length < 2)
495
 
                                        return false;
496
 
 
497
 
                                if (this[0] != DType.Array)
498
 
                                        return false;
499
 
 
500
 
                                return true;
501
 
                        }
502
 
                }
503
 
 
504
 
                public Signature GetElementSignature ()
505
 
                {
506
 
                        if (!IsArray)
507
 
                                throw new Exception ("Cannot get the element signature of a non-array (signature was '" + this + "')");
508
 
 
509
 
                        //TODO: improve this
510
 
                        //if (IsDict)
511
 
                        //      throw new NotSupportedException ("Parsing dict signature is not supported (signature was '" + this + "')");
512
 
 
513
 
                        // Skip over 'a'
514
 
                        int pos = 1;
515
 
                        return GetNextSignature (ref pos);
516
 
                }
517
 
 
518
 
                public Type[] ToTypes ()
519
 
                {
520
 
                        // TODO: Find a way to avoid these null checks everywhere.
521
 
                        if (data == null)
522
 
                                return Type.EmptyTypes;
523
 
 
524
 
                        List<Type> types = new List<Type> ();
525
 
                        for (int i = 0 ; i != data.Length ; types.Add (ToType (ref i)));
526
 
                        return types.ToArray ();
527
 
                }
528
 
 
529
 
                public Type ToType ()
530
 
                {
531
 
                        int pos = 0;
532
 
                        Type ret = ToType (ref pos);
533
 
                        if (pos != data.Length)
534
 
                                throw new Exception ("Signature '" + Value + "' is not a single complete type");
535
 
                        return ret;
536
 
                }
537
 
 
538
 
                internal static DType TypeCodeToDType (TypeCode typeCode)
539
 
                {
540
 
                        switch (typeCode)
541
 
                        {
542
 
                                case TypeCode.Empty:
543
 
                                        return DType.Invalid;
544
 
                                case TypeCode.Object:
545
 
                                        return DType.Invalid;
546
 
                                case TypeCode.DBNull:
547
 
                                        return DType.Invalid;
548
 
                                case TypeCode.Boolean:
549
 
                                        return DType.Boolean;
550
 
                                case TypeCode.Char:
551
 
                                        return DType.UInt16;
552
 
                                case TypeCode.SByte:
553
 
                                        return DType.Byte;
554
 
                                case TypeCode.Byte:
555
 
                                        return DType.Byte;
556
 
                                case TypeCode.Int16:
557
 
                                        return DType.Int16;
558
 
                                case TypeCode.UInt16:
559
 
                                        return DType.UInt16;
560
 
                                case TypeCode.Int32:
561
 
                                        return DType.Int32;
562
 
                                case TypeCode.UInt32:
563
 
                                        return DType.UInt32;
564
 
                                case TypeCode.Int64:
565
 
                                        return DType.Int64;
566
 
                                case TypeCode.UInt64:
567
 
                                        return DType.UInt64;
568
 
                                case TypeCode.Single:
569
 
                                        return DType.Single;
570
 
                                case TypeCode.Double:
571
 
                                        return DType.Double;
572
 
                                case TypeCode.Decimal:
573
 
                                        return DType.Invalid;
574
 
                                case TypeCode.DateTime:
575
 
                                        return DType.Invalid;
576
 
                                case TypeCode.String:
577
 
                                        return DType.String;
578
 
                                default:
579
 
                                        return DType.Invalid;
580
 
                        }
581
 
                }
582
 
 
583
 
                //FIXME: this method is bad, get rid of it
584
 
                internal static DType TypeToDType (Type type)
585
 
                {
586
 
                        if (type == typeof (void))
587
 
                                return DType.Invalid;
588
 
 
589
 
                        if (type == typeof (string))
590
 
                                return DType.String;
591
 
 
592
 
                        if (type == typeof (ObjectPath))
593
 
                                return DType.ObjectPath;
594
 
 
595
 
                        if (type == typeof (Signature))
596
 
                                return DType.Signature;
597
 
 
598
 
                        if (type == typeof (object))
599
 
                                return DType.Variant;
600
 
 
601
 
                        if (type.IsPrimitive)
602
 
                                return TypeCodeToDType (Type.GetTypeCode (type));
603
 
 
604
 
                        if (type.IsEnum)
605
 
                                return TypeToDType (Enum.GetUnderlyingType (type));
606
 
 
607
 
                        //needs work
608
 
                        if (type.IsArray)
609
 
                                return DType.Array;
610
 
 
611
 
                        //if (type.UnderlyingSystemType != null)
612
 
                        //      return TypeToDType (type.UnderlyingSystemType);
613
 
                        if (Mapper.IsPublic (type))
614
 
                                return DType.ObjectPath;
615
 
 
616
 
                        if (!type.IsPrimitive && !type.IsEnum)
617
 
                                return DType.Struct;
618
 
 
619
 
                        //TODO: maybe throw an exception here
620
 
                        return DType.Invalid;
621
 
                }
622
 
 
623
 
                /*
624
 
                public static DType TypeToDType (Type type)
625
 
                {
626
 
                        if (type == null)
627
 
                                return DType.Invalid;
628
 
                        else if (type == typeof (byte))
629
 
                                return DType.Byte;
630
 
                        else if (type == typeof (bool))
631
 
                                return DType.Boolean;
632
 
                        else if (type == typeof (short))
633
 
                                return DType.Int16;
634
 
                        else if (type == typeof (ushort))
635
 
                                return DType.UInt16;
636
 
                        else if (type == typeof (int))
637
 
                                return DType.Int32;
638
 
                        else if (type == typeof (uint))
639
 
                                return DType.UInt32;
640
 
                        else if (type == typeof (long))
641
 
                                return DType.Int64;
642
 
                        else if (type == typeof (ulong))
643
 
                                return DType.UInt64;
644
 
                        else if (type == typeof (float)) //not supported by libdbus at time of writing
645
 
                                return DType.Single;
646
 
                        else if (type == typeof (double))
647
 
                                return DType.Double;
648
 
                        else if (type == typeof (string))
649
 
                                return DType.String;
650
 
                        else if (type == typeof (ObjectPath))
651
 
                                return DType.ObjectPath;
652
 
                        else if (type == typeof (Signature))
653
 
                                return DType.Signature;
654
 
                        else
655
 
                                return DType.Invalid;
656
 
                }
657
 
                */
658
 
 
659
 
                public IEnumerable<Signature> GetFieldSignatures ()
660
 
                {
661
 
                        if (this == Signature.Empty || this[0] != DType.StructBegin)
662
 
                                throw new Exception ("Not a struct");
663
 
 
664
 
                        for (int pos = 1 ; pos < data.Length - 1 ;)
665
 
                                yield return GetNextSignature (ref pos);
666
 
                }
667
 
 
668
 
                public void GetDictEntrySignatures (out Signature sigKey, out Signature sigValue)
669
 
                {
670
 
                        if (this == Signature.Empty || this[0] != DType.DictEntryBegin)
671
 
                                throw new Exception ("Not a DictEntry");
672
 
 
673
 
                        int pos = 1;
674
 
                        sigKey = GetNextSignature (ref pos);
675
 
                        sigValue = GetNextSignature (ref pos);
676
 
                }
677
 
 
678
 
                public IEnumerable<Signature> GetParts ()
679
 
                {
680
 
                        if (data == null)
681
 
                                yield break;
682
 
                        for (int pos = 0 ; pos < data.Length ;) {
683
 
                                yield return GetNextSignature (ref pos);
684
 
                        }
685
 
                }
686
 
 
687
 
                public Signature GetNextSignature (ref int pos)
688
 
                {
689
 
                        if (data == null)
690
 
                                return Signature.Empty;
691
 
 
692
 
                        DType dtype = (DType)data[pos++];
693
 
 
694
 
                        switch (dtype) {
695
 
                                //case DType.Invalid:
696
 
                                //      return typeof (void);
697
 
                                case DType.Array:
698
 
                                        //peek to see if this is in fact a dictionary
699
 
                                        if ((DType)data[pos] == DType.DictEntryBegin) {
700
 
                                                //skip over the {
701
 
                                                pos++;
702
 
                                                Signature keyType = GetNextSignature (ref pos);
703
 
                                                Signature valueType = GetNextSignature (ref pos);
704
 
                                                //skip over the }
705
 
                                                pos++;
706
 
                                                return Signature.MakeDict (keyType, valueType);
707
 
                                        } else {
708
 
                                                Signature elementType = GetNextSignature (ref pos);
709
 
                                                return elementType.MakeArraySignature ();
710
 
                                        }
711
 
                                //case DType.DictEntryBegin: // FIXME: DictEntries should be handled separately.
712
 
                                case DType.StructBegin:
713
 
                                        //List<Signature> fieldTypes = new List<Signature> ();
714
 
                                        Signature fieldsSig = Signature.Empty;
715
 
                                        while ((DType)data[pos] != DType.StructEnd)
716
 
                                                fieldsSig += GetNextSignature (ref pos);
717
 
                                        //skip over the )
718
 
                                        pos++;
719
 
                                        return Signature.MakeStruct (fieldsSig);
720
 
                                        //return fieldsSig;
721
 
                                case DType.DictEntryBegin:
722
 
                                        Signature sigKey = GetNextSignature (ref pos);
723
 
                                        Signature sigValue = GetNextSignature (ref pos);
724
 
                                        //skip over the }
725
 
                                        pos++;
726
 
                                        return Signature.MakeDictEntry (sigKey, sigValue);
727
 
                                default:
728
 
                                        return new Signature (dtype);
729
 
                        }
730
 
                }
731
 
 
732
 
                public Type ToType (ref int pos)
733
 
                {
734
 
                        // TODO: Find a way to avoid these null checks everywhere.
735
 
                        if (data == null)
736
 
                                return typeof (void);
737
 
 
738
 
                        DType dtype = (DType)data[pos++];
739
 
 
740
 
                        switch (dtype) {
741
 
                                case DType.Invalid:
742
 
                                        return typeof (void);
743
 
                                case DType.Byte:
744
 
                                        return typeof (byte);
745
 
                                case DType.Boolean:
746
 
                                        return typeof (bool);
747
 
                                case DType.Int16:
748
 
                                        return typeof (short);
749
 
                                case DType.UInt16:
750
 
                                        return typeof (ushort);
751
 
                                case DType.Int32:
752
 
                                        return typeof (int);
753
 
                                case DType.UInt32:
754
 
                                        return typeof (uint);
755
 
                                case DType.Int64:
756
 
                                        return typeof (long);
757
 
                                case DType.UInt64:
758
 
                                        return typeof (ulong);
759
 
                                case DType.Single: ////not supported by libdbus at time of writing
760
 
                                        return typeof (float);
761
 
                                case DType.Double:
762
 
                                        return typeof (double);
763
 
                                case DType.String:
764
 
                                        return typeof (string);
765
 
                                case DType.ObjectPath:
766
 
                                        return typeof (ObjectPath);
767
 
                                case DType.Signature:
768
 
                                        return typeof (Signature);
769
 
                                case DType.Array:
770
 
                                        //peek to see if this is in fact a dictionary
771
 
                                        if ((DType)data[pos] == DType.DictEntryBegin) {
772
 
                                                //skip over the {
773
 
                                                pos++;
774
 
                                                Type keyType = ToType (ref pos);
775
 
                                                Type valueType = ToType (ref pos);
776
 
                                                //skip over the }
777
 
                                                pos++;
778
 
                                                //return typeof (IDictionary<,>).MakeGenericType (new Type[] {keyType, valueType});
779
 
                                                //workaround for Mono bug #81035 (memory leak)
780
 
                                                return Mapper.GetGenericType (typeof (IDictionary<,>), new Type[] {keyType, valueType});
781
 
                                        } else {
782
 
                                                return ToType (ref pos).MakeArrayType ();
783
 
                                        }
784
 
                                case DType.Struct:
785
 
                                        return typeof (ValueType);
786
 
                                case DType.DictEntry:
787
 
                                        return typeof (System.Collections.Generic.KeyValuePair<,>);
788
 
                                case DType.Variant:
789
 
                                        return typeof (object);
790
 
                                default:
791
 
                                        throw new NotSupportedException ("Parsing or converting this signature is not yet supported (signature was '" + this + "'), at DType." + dtype);
792
 
                        }
793
 
                }
794
 
 
795
 
                public static Signature GetSig (object[] objs)
796
 
                {
797
 
                        return GetSig (Type.GetTypeArray (objs));
798
 
                }
799
 
 
800
 
                public static Signature GetSig (Type[] types)
801
 
                {
802
 
                        if (types == null)
803
 
                                throw new ArgumentNullException ("types");
804
 
 
805
 
                        Signature sig = Signature.Empty;
806
 
 
807
 
                        foreach (Type type in types)
808
 
                                        sig += GetSig (type);
809
 
 
810
 
                        return sig;
811
 
                }
812
 
 
813
 
                public static Signature GetSig (Type type)
814
 
                {
815
 
                        if (type == null)
816
 
                                throw new ArgumentNullException ("type");
817
 
 
818
 
                        //this is inelegant, but works for now
819
 
                        if (type == typeof (Signature))
820
 
                                return new Signature (DType.Signature);
821
 
 
822
 
                        if (type == typeof (ObjectPath))
823
 
                                return new Signature (DType.ObjectPath);
824
 
 
825
 
                        if (type == typeof (void))
826
 
                                return Signature.Empty;
827
 
 
828
 
                        if (type == typeof (string))
829
 
                                return new Signature (DType.String);
830
 
 
831
 
                        if (type == typeof (object))
832
 
                                return new Signature (DType.Variant);
833
 
 
834
 
                        if (type.IsArray)
835
 
                                return GetSig (type.GetElementType ()).MakeArraySignature ();
836
 
 
837
 
                        if (type.IsGenericType && (type.GetGenericTypeDefinition () == typeof (IDictionary<,>) || type.GetGenericTypeDefinition () == typeof (Dictionary<,>))) {
838
 
 
839
 
                                Type[] genArgs = type.GetGenericArguments ();
840
 
                                return Signature.MakeDict (GetSig (genArgs[0]), GetSig (genArgs[1]));
841
 
                        }
842
 
 
843
 
                        if (Mapper.IsPublic (type)) {
844
 
                                return new Signature (DType.ObjectPath);
845
 
                        }
846
 
 
847
 
                        if (!type.IsPrimitive && !type.IsEnum) {
848
 
                                Signature sig = Signature.Empty;
849
 
 
850
 
                                foreach (FieldInfo fi in type.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
851
 
                                        sig += GetSig (fi.FieldType);
852
 
 
853
 
                                return Signature.MakeStruct (sig);
854
 
                        }
855
 
 
856
 
                        DType dtype = Signature.TypeToDType (type);
857
 
                        return new Signature (dtype);
858
 
                }
859
 
        }
860
 
 
861
 
        enum ArgDirection
862
 
        {
863
 
                In,
864
 
                Out,
865
 
        }
866
 
 
867
 
        enum DType : byte
868
 
        {
869
 
                Invalid = (byte)'\0',
870
 
 
871
 
                Byte = (byte)'y',
872
 
                Boolean = (byte)'b',
873
 
                Int16 = (byte)'n',
874
 
                UInt16 = (byte)'q',
875
 
                Int32 = (byte)'i',
876
 
                UInt32 = (byte)'u',
877
 
                Int64 = (byte)'x',
878
 
                UInt64 = (byte)'t',
879
 
                Single = (byte)'f', //This is not yet supported!
880
 
                Double = (byte)'d',
881
 
                String = (byte)'s',
882
 
                ObjectPath = (byte)'o',
883
 
                Signature = (byte)'g',
884
 
 
885
 
                Array = (byte)'a',
886
 
                [Obsolete ("Not in protocol")]
887
 
                Struct = (byte)'r',
888
 
                [Obsolete ("Not in protocol")]
889
 
                DictEntry = (byte)'e',
890
 
                Variant = (byte)'v',
891
 
 
892
 
                StructBegin = (byte)'(',
893
 
                StructEnd = (byte)')',
894
 
                DictEntryBegin = (byte)'{',
895
 
                DictEntryEnd = (byte)'}',
896
 
        }
897
 
}