2
Copyright (C) 2011 Jeroen Frijters
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.
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:
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.
25
using System.Collections.Generic;
26
using System.Diagnostics;
28
using IKVM.Reflection.Emit;
29
using IKVM.Reflection.Reader;
31
namespace IKVM.Reflection
33
public struct CustomModifiers : IEquatable<CustomModifiers>, IEnumerable<CustomModifiers.Entry>
35
// note that FromReqOpt assumes that Initial == ModOpt
36
private static Type Initial { get { return MarkerType.ModOpt; } }
37
private readonly Type[] types;
39
internal CustomModifiers(List<CustomModifiersBuilder.Item> list)
41
bool required = Initial == MarkerType.ModReq;
42
int count = list.Count;
43
foreach (CustomModifiersBuilder.Item item in list)
45
if (item.required != required)
47
required = item.required;
51
types = new Type[count];
52
required = Initial == MarkerType.ModReq;
54
foreach (CustomModifiersBuilder.Item item in list)
56
if (item.required != required)
58
required = item.required;
59
types[index++] = required ? MarkerType.ModReq : MarkerType.ModOpt;
61
types[index++] = item.type;
65
private CustomModifiers(Type[] types)
67
Debug.Assert(types == null || types.Length != 0);
71
public struct Enumerator : IEnumerator<Entry>
73
private readonly Type[] types;
75
private bool required;
77
internal Enumerator(Type[] types)
81
this.required = Initial == MarkerType.ModReq;
84
void System.Collections.IEnumerator.Reset()
87
this.required = Initial == MarkerType.ModReq;
92
get { return new Entry(types[index], required); }
95
public bool MoveNext()
97
if (types == null || index == types.Length)
102
if (index == types.Length)
106
else if (types[index] == MarkerType.ModOpt)
111
else if (types[index] == MarkerType.ModReq)
119
object System.Collections.IEnumerator.Current
121
get { return Current; }
124
void IDisposable.Dispose()
131
private readonly Type type;
132
private readonly bool required;
134
internal Entry(Type type, bool required)
137
this.required = required;
145
public bool IsRequired
147
get { return required; }
151
public Enumerator GetEnumerator()
153
return new Enumerator(types);
156
IEnumerator<Entry> IEnumerable<Entry>.GetEnumerator()
158
return GetEnumerator();
161
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
163
return GetEnumerator();
168
get { return types == null; }
171
public bool Equals(CustomModifiers other)
173
return Util.ArrayEquals(types, other.types);
176
public override bool Equals(object obj)
178
CustomModifiers? other = obj as CustomModifiers?;
179
return other != null && Equals(other.Value);
182
public override int GetHashCode()
184
return Util.GetHashCode(types);
187
public override string ToString()
193
StringBuilder sb = new StringBuilder();
195
foreach (Entry e in this)
197
sb.Append(sep).Append(e.IsRequired ? "modreq(" : "modopt(").Append(e.Type.FullName).Append(')');
200
return sb.ToString();
203
private Type[] GetRequiredOrOptional(bool required)
207
return Type.EmptyTypes;
210
foreach (Entry e in this)
212
if (e.IsRequired == required)
217
Type[] result = new Type[count];
218
foreach (Entry e in this)
220
if (e.IsRequired == required)
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;
230
internal Type[] GetRequired()
232
return GetRequiredOrOptional(true);
235
internal Type[] GetOptional()
237
return GetRequiredOrOptional(false);
240
internal CustomModifiers Bind(IGenericBinder binder)
246
Type[] result = types;
247
for (int i = 0; i < types.Length; i++)
249
if (types[i] == MarkerType.ModOpt || types[i] == MarkerType.ModReq)
253
Type type = types[i].BindTypeParameters(binder);
254
if (!ReferenceEquals(type, types[i]))
258
result = (Type[])types.Clone();
263
return new CustomModifiers(result);
266
internal static CustomModifiers Read(ModuleReader module, ByteReader br, IGenericContext context)
268
byte b = br.PeekByte();
269
if (!IsCustomModifier(b))
271
return new CustomModifiers();
273
List<Type> list = new List<Type>();
277
Type cmod = br.ReadByte() == Signature.ELEMENT_TYPE_CMOD_REQD ? MarkerType.ModReq : MarkerType.ModOpt;
283
list.Add(Signature.ReadTypeDefOrRefEncoded(module, br, context));
286
while (IsCustomModifier(b));
287
return new CustomModifiers(list.ToArray());
290
internal static void Skip(ByteReader br)
292
byte b = br.PeekByte();
293
while (IsCustomModifier(b))
296
br.ReadCompressedUInt();
301
internal static CustomModifiers FromReqOpt(Type[] req, Type[] opt)
303
List<Type> list = null;
304
if (opt != null && opt.Length != 0)
306
Debug.Assert(Initial == MarkerType.ModOpt);
307
list = new List<Type>(opt);
309
if (req != null && req.Length != 0)
313
list = new List<Type>();
315
list.Add(MarkerType.ModReq);
320
return new CustomModifiers();
324
return new CustomModifiers(list.ToArray());
328
private static bool IsCustomModifier(byte b)
330
return b == Signature.ELEMENT_TYPE_CMOD_OPT || b == Signature.ELEMENT_TYPE_CMOD_REQD;
333
internal static CustomModifiers Combine(CustomModifiers mods1, CustomModifiers mods2)
339
else if (mods2.IsEmpty)
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);