~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/reflect/CustomModifiers.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
ļ»æ/*
 
2
  Copyright (C) 2011 Jeroen Frijters
 
3
 
 
4
  This software is provided 'as-is', without any express or implied
 
5
  warranty.  In no event will the authors be held liable for any damages
 
6
  arising from the use of this software.
 
7
 
 
8
  Permission is granted to anyone to use this software for any purpose,
 
9
  including commercial applications, and to alter it and redistribute it
 
10
  freely, subject to the following restrictions:
 
11
 
 
12
  1. The origin of this software must not be misrepresented; you must not
 
13
     claim that you wrote the original software. If you use this software
 
14
     in a product, an acknowledgment in the product documentation would be
 
15
     appreciated but is not required.
 
16
  2. Altered source versions must be plainly marked as such, and must not be
 
17
     misrepresented as being the original software.
 
18
  3. This notice may not be removed or altered from any source distribution.
 
19
 
 
20
  Jeroen Frijters
 
21
  jeroen@frijters.net
 
22
  
 
23
*/
 
24
using System;
 
25
using System.Collections.Generic;
 
26
using System.Diagnostics;
 
27
using System.Text;
 
28
using IKVM.Reflection.Emit;
 
29
using IKVM.Reflection.Reader;
 
30
 
 
31
namespace IKVM.Reflection
 
32
{
 
33
        public struct CustomModifiers : IEquatable<CustomModifiers>, IEnumerable<CustomModifiers.Entry>
 
34
        {
 
35
                // note that FromReqOpt assumes that Initial == ModOpt
 
36
                private static Type Initial { get { return MarkerType.ModOpt; } }
 
37
                private readonly Type[] types;
 
38
 
 
39
                internal CustomModifiers(List<CustomModifiersBuilder.Item> list)
 
40
                {
 
41
                        bool required = Initial == MarkerType.ModReq;
 
42
                        int count = list.Count;
 
43
                        foreach (CustomModifiersBuilder.Item item in list)
 
44
                        {
 
45
                                if (item.required != required)
 
46
                                {
 
47
                                        required = item.required;
 
48
                                        count++;
 
49
                                }
 
50
                        }
 
51
                        types = new Type[count];
 
52
                        required = Initial == MarkerType.ModReq;
 
53
                        int index = 0;
 
54
                        foreach (CustomModifiersBuilder.Item item in list)
 
55
                        {
 
56
                                if (item.required != required)
 
57
                                {
 
58
                                        required = item.required;
 
59
                                        types[index++] = required ? MarkerType.ModReq : MarkerType.ModOpt;
 
60
                                }
 
61
                                types[index++] = item.type;
 
62
                        }
 
63
                }
 
64
 
 
65
                private CustomModifiers(Type[] types)
 
66
                {
 
67
                        Debug.Assert(types == null || types.Length != 0);
 
68
                        this.types = types;
 
69
                }
 
70
 
 
71
                public struct Enumerator : IEnumerator<Entry>
 
72
                {
 
73
                        private readonly Type[] types;
 
74
                        private int index;
 
75
                        private bool required;
 
76
 
 
77
                        internal Enumerator(Type[] types)
 
78
                        {
 
79
                                this.types = types;
 
80
                                this.index = -1;
 
81
                                this.required = Initial == MarkerType.ModReq;
 
82
                        }
 
83
 
 
84
                        void System.Collections.IEnumerator.Reset()
 
85
                        {
 
86
                                this.index = -1;
 
87
                                this.required = Initial == MarkerType.ModReq;
 
88
                        }
 
89
 
 
90
                        public Entry Current
 
91
                        {
 
92
                                get { return new Entry(types[index], required); }
 
93
                        }
 
94
 
 
95
                        public bool MoveNext()
 
96
                        {
 
97
                                if (types == null || index == types.Length)
 
98
                                {
 
99
                                        return false;
 
100
                                }
 
101
                                index++;
 
102
                                if (index == types.Length)
 
103
                                {
 
104
                                        return false;
 
105
                                }
 
106
                                else if (types[index] == MarkerType.ModOpt)
 
107
                                {
 
108
                                        required = false;
 
109
                                        index++;
 
110
                                }
 
111
                                else if (types[index] == MarkerType.ModReq)
 
112
                                {
 
113
                                        required = true;
 
114
                                        index++;
 
115
                                }
 
116
                                return true;
 
117
                        }
 
118
 
 
119
                        object System.Collections.IEnumerator.Current
 
120
                        {
 
121
                                get { return Current; }
 
122
                        }
 
123
 
 
124
                        void IDisposable.Dispose()
 
125
                        {
 
126
                        }
 
127
                }
 
128
 
 
129
                public struct Entry
 
130
                {
 
131
                        private readonly Type type;
 
132
                        private readonly bool required;
 
133
 
 
134
                        internal Entry(Type type, bool required)
 
135
                        {
 
136
                                this.type = type;
 
137
                                this.required = required;
 
138
                        }
 
139
 
 
140
                        public Type Type
 
141
                        {
 
142
                                get { return type; }
 
143
                        }
 
144
 
 
145
                        public bool IsRequired
 
146
                        {
 
147
                                get { return required; }
 
148
                        }
 
149
                }
 
150
 
 
151
                public Enumerator GetEnumerator()
 
152
                {
 
153
                        return new Enumerator(types);
 
154
                }
 
155
 
 
156
                IEnumerator<Entry> IEnumerable<Entry>.GetEnumerator()
 
157
                {
 
158
                        return GetEnumerator();
 
159
                }
 
160
 
 
161
                System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
 
162
                {
 
163
                        return GetEnumerator();
 
164
                }
 
165
 
 
166
                public bool IsEmpty
 
167
                {
 
168
                        get { return types == null; }
 
169
                }
 
170
 
 
171
                public bool Equals(CustomModifiers other)
 
172
                {
 
173
                        return Util.ArrayEquals(types, other.types);
 
174
                }
 
175
 
 
176
                public override bool Equals(object obj)
 
177
                {
 
178
                        CustomModifiers? other = obj as CustomModifiers?;
 
179
                        return other != null && Equals(other.Value);
 
180
                }
 
181
 
 
182
                public override int GetHashCode()
 
183
                {
 
184
                        return Util.GetHashCode(types);
 
185
                }
 
186
 
 
187
                public override string ToString()
 
188
                {
 
189
                        if (types == null)
 
190
                        {
 
191
                                return string.Empty;
 
192
                        }
 
193
                        StringBuilder sb = new StringBuilder();
 
194
                        string sep = "";
 
195
                        foreach (Entry e in this)
 
196
                        {
 
197
                                sb.Append(sep).Append(e.IsRequired ? "modreq(" : "modopt(").Append(e.Type.FullName).Append(')');
 
198
                                sep = " ";
 
199
                        }
 
200
                        return sb.ToString();
 
201
                }
 
202
 
 
203
                private Type[] GetRequiredOrOptional(bool required)
 
204
                {
 
205
                        if (types == null)
 
206
                        {
 
207
                                return Type.EmptyTypes;
 
208
                        }
 
209
                        int count = 0;
 
210
                        foreach (Entry e in this)
 
211
                        {
 
212
                                if (e.IsRequired == required)
 
213
                                {
 
214
                                        count++;
 
215
                                }
 
216
                        }
 
217
                        Type[] result = new Type[count];
 
218
                        foreach (Entry e in this)
 
219
                        {
 
220
                                if (e.IsRequired == required)
 
221
                                {
 
222
                                        // FXBUG reflection (and ildasm) return custom modifiers in reverse order
 
223
                                        // while SRE writes them in the specified order
 
224
                                        result[--count] = e.Type;
 
225
                                }
 
226
                        }
 
227
                        return result;
 
228
                }
 
229
 
 
230
                internal Type[] GetRequired()
 
231
                {
 
232
                        return GetRequiredOrOptional(true);
 
233
                }
 
234
 
 
235
                internal Type[] GetOptional()
 
236
                {
 
237
                        return GetRequiredOrOptional(false);
 
238
                }
 
239
 
 
240
                internal CustomModifiers Bind(IGenericBinder binder)
 
241
                {
 
242
                        if (types == null)
 
243
                        {
 
244
                                return this;
 
245
                        }
 
246
                        Type[] result = types;
 
247
                        for (int i = 0; i < types.Length; i++)
 
248
                        {
 
249
                                if (types[i] == MarkerType.ModOpt || types[i] == MarkerType.ModReq)
 
250
                                {
 
251
                                        continue;
 
252
                                }
 
253
                                Type type = types[i].BindTypeParameters(binder);
 
254
                                if (!ReferenceEquals(type, types[i]))
 
255
                                {
 
256
                                        if (result == types)
 
257
                                        {
 
258
                                                result = (Type[])types.Clone();
 
259
                                        }
 
260
                                        result[i] = type;
 
261
                                }
 
262
                        }
 
263
                        return new CustomModifiers(result);
 
264
                }
 
265
 
 
266
                internal static CustomModifiers Read(ModuleReader module, ByteReader br, IGenericContext context)
 
267
                {
 
268
                        byte b = br.PeekByte();
 
269
                        if (!IsCustomModifier(b))
 
270
                        {
 
271
                                return new CustomModifiers();
 
272
                        }
 
273
                        List<Type> list = new List<Type>();
 
274
                        Type mode = Initial;
 
275
                        do
 
276
                        {
 
277
                                Type cmod = br.ReadByte() == Signature.ELEMENT_TYPE_CMOD_REQD ? MarkerType.ModReq : MarkerType.ModOpt;
 
278
                                if (mode != cmod)
 
279
                                {
 
280
                                        mode = cmod;
 
281
                                        list.Add(mode);
 
282
                                }
 
283
                                list.Add(Signature.ReadTypeDefOrRefEncoded(module, br, context));
 
284
                                b = br.PeekByte();
 
285
                        }
 
286
                        while (IsCustomModifier(b));
 
287
                        return new CustomModifiers(list.ToArray());
 
288
                }
 
289
 
 
290
                internal static void Skip(ByteReader br)
 
291
                {
 
292
                        byte b = br.PeekByte();
 
293
                        while (IsCustomModifier(b))
 
294
                        {
 
295
                                br.ReadByte();
 
296
                                br.ReadCompressedUInt();
 
297
                                b = br.PeekByte();
 
298
                        }
 
299
                }
 
300
 
 
301
                internal static CustomModifiers FromReqOpt(Type[] req, Type[] opt)
 
302
                {
 
303
                        List<Type> list = null;
 
304
                        if (opt != null && opt.Length != 0)
 
305
                        {
 
306
                                Debug.Assert(Initial == MarkerType.ModOpt);
 
307
                                list = new List<Type>(opt);
 
308
                        }
 
309
                        if (req != null && req.Length != 0)
 
310
                        {
 
311
                                if (list == null)
 
312
                                {
 
313
                                        list = new List<Type>();
 
314
                                }
 
315
                                list.Add(MarkerType.ModReq);
 
316
                                list.AddRange(req);
 
317
                        }
 
318
                        if (list == null)
 
319
                        {
 
320
                                return new CustomModifiers();
 
321
                        }
 
322
                        else
 
323
                        {
 
324
                                return new CustomModifiers(list.ToArray());
 
325
                        }
 
326
                }
 
327
 
 
328
                private static bool IsCustomModifier(byte b)
 
329
                {
 
330
                        return b == Signature.ELEMENT_TYPE_CMOD_OPT || b == Signature.ELEMENT_TYPE_CMOD_REQD;
 
331
                }
 
332
 
 
333
                internal static CustomModifiers Combine(CustomModifiers mods1, CustomModifiers mods2)
 
334
                {
 
335
                        if (mods1.IsEmpty)
 
336
                        {
 
337
                                return mods2;
 
338
                        }
 
339
                        else if (mods2.IsEmpty)
 
340
                        {
 
341
                                return mods1;
 
342
                        }
 
343
                        else
 
344
                        {
 
345
                                Type[] combo = new Type[mods1.types.Length + mods2.types.Length];
 
346
                                Array.Copy(mods1.types, combo, mods1.types.Length);
 
347
                                Array.Copy(mods2.types, 0, combo, mods1.types.Length, mods2.types.Length);
 
348
                                return new CustomModifiers(combo);
 
349
                        }
 
350
                }
 
351
        }
 
352
}