Merge branch 'bugfix'
[mono.git] / mcs / class / IKVM.Reflection / PropertySignature.cs
1 /*
2   Copyright (C) 2009 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.IO;
27 using System.Text;
28 using IKVM.Reflection.Emit;
29 using IKVM.Reflection.Writer;
30 using IKVM.Reflection.Reader;
31
32 namespace IKVM.Reflection
33 {
34         sealed class PropertySignature : Signature
35         {
36                 private CallingConventions callingConvention;
37                 private readonly Type propertyType;
38                 private readonly Type[] optionalCustomModifiers;
39                 private readonly Type[] requiredCustomModifiers;
40                 private readonly Type[] parameterTypes;
41                 private readonly Type[][] parameterOptionalCustomModifiers;
42                 private readonly Type[][] parameterRequiredCustomModifiers;
43
44                 internal static PropertySignature Create(CallingConventions callingConvention, Type propertyType, Type[] optionalCustomModifiers, Type[] requiredCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeOptionalCustomModifiers, Type[][] parameterTypeRequiredCustomModifiers)
45                 {
46                         return new PropertySignature(callingConvention, propertyType, Util.Copy(optionalCustomModifiers), Util.Copy(requiredCustomModifiers), Util.Copy(parameterTypes), Util.Copy(parameterTypeOptionalCustomModifiers), Util.Copy(parameterTypeRequiredCustomModifiers));
47                 }
48
49                 private PropertySignature(CallingConventions callingConvention, Type propertyType, Type[] optionalCustomModifiers, Type[] requiredCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeOptionalCustomModifiers, Type[][] parameterTypeRequiredCustomModifiers)
50                 {
51                         this.callingConvention = callingConvention;
52                         this.propertyType = propertyType;
53                         this.optionalCustomModifiers = optionalCustomModifiers;
54                         this.requiredCustomModifiers = requiredCustomModifiers;
55                         this.parameterTypes = parameterTypes;
56                         this.parameterOptionalCustomModifiers = parameterTypeOptionalCustomModifiers;
57                         this.parameterRequiredCustomModifiers = parameterTypeRequiredCustomModifiers;
58                 }
59
60                 public override bool Equals(object obj)
61                 {
62                         PropertySignature other = obj as PropertySignature;
63                         return other != null
64                                 && other.propertyType.Equals(propertyType)
65                                 && Util.ArrayEquals(other.optionalCustomModifiers, optionalCustomModifiers)
66                                 && Util.ArrayEquals(other.requiredCustomModifiers, requiredCustomModifiers);
67                 }
68
69                 public override int GetHashCode()
70                 {
71                         return propertyType.GetHashCode() ^ Util.GetHashCode(optionalCustomModifiers) ^ Util.GetHashCode(requiredCustomModifiers);
72                 }
73
74                 internal int ParameterCount
75                 {
76                         get { return parameterTypes.Length; }
77                 }
78
79                 internal bool HasThis
80                 {
81                         set
82                         {
83                                 if (value)
84                                 {
85                                         callingConvention |= CallingConventions.HasThis;
86                                 }
87                                 else
88                                 {
89                                         callingConvention &= ~CallingConventions.HasThis;
90                                 }
91                         }
92                 }
93
94                 internal Type PropertyType
95                 {
96                         get { return propertyType; }
97                 }
98
99                 internal Type[] GetOptionalCustomModifiers()
100                 {
101                         return Util.Copy(optionalCustomModifiers);
102                 }
103
104                 internal Type[] GetRequiredCustomModifiers()
105                 {
106                         return Util.Copy(requiredCustomModifiers);
107                 }
108
109                 internal PropertySignature ExpandTypeParameters(Type declaringType)
110                 {
111                         return new PropertySignature(
112                                 callingConvention,
113                                 propertyType.BindTypeParameters(declaringType),
114                                 BindTypeParameters(declaringType, optionalCustomModifiers),
115                                 BindTypeParameters(declaringType, requiredCustomModifiers),
116                                 BindTypeParameters(declaringType, parameterTypes),
117                                 BindTypeParameters(declaringType, parameterOptionalCustomModifiers),
118                                 BindTypeParameters(declaringType, parameterRequiredCustomModifiers));
119                 }
120
121                 internal override void WriteSig(ModuleBuilder module, ByteBuffer bb)
122                 {
123                         byte flags = PROPERTY;
124                         if ((callingConvention & CallingConventions.HasThis) != 0)
125                         {
126                                 flags |= HASTHIS;
127                         }
128                         if ((callingConvention & CallingConventions.ExplicitThis) != 0)
129                         {
130                                 flags |= EXPLICITTHIS;
131                         }
132                         if ((callingConvention & CallingConventions.VarArgs) != 0)
133                         {
134                                 flags |= VARARG;
135                         }
136                         bb.Write(flags);
137                         bb.WriteCompressedInt(parameterTypes == null ? 0 : parameterTypes.Length);
138                         WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, requiredCustomModifiers);
139                         WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, optionalCustomModifiers);
140                         WriteType(module, bb, propertyType);
141                         if (parameterTypes != null)
142                         {
143                                 for (int i = 0; i < parameterTypes.Length; i++)
144                                 {
145                                         if (parameterRequiredCustomModifiers != null)
146                                         {
147                                                 WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, parameterRequiredCustomModifiers[i]);
148                                         }
149                                         if (parameterOptionalCustomModifiers != null)
150                                         {
151                                                 WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, parameterOptionalCustomModifiers[i]);
152                                         }
153                                         WriteType(module, bb, parameterTypes[i]);
154                                 }
155                         }
156                 }
157
158                 internal Type GetParameter(int parameter)
159                 {
160                         return parameterTypes[parameter];
161                 }
162
163                 internal Type[] GetOptionalCustomModifiers(int parameter)
164                 {
165                         return parameterOptionalCustomModifiers == null ? Type.EmptyTypes : parameterOptionalCustomModifiers[parameter];
166                 }
167
168                 internal Type[] GetRequiredCustomModifiers(int parameter)
169                 {
170                         return parameterRequiredCustomModifiers == null ? Type.EmptyTypes : parameterRequiredCustomModifiers[parameter];
171                 }
172
173                 internal CallingConventions CallingConvention
174                 {
175                         get { return callingConvention; }
176                 }
177
178                 internal static PropertySignature ReadSig(ModuleReader module, ByteReader br, IGenericContext context)
179                 {
180                         byte flags = br.ReadByte();
181                         if ((flags & PROPERTY) == 0)
182                         {
183                                 throw new BadImageFormatException();
184                         }
185                         CallingConventions callingConvention = CallingConventions.Standard;
186                         if ((flags & HASTHIS) != 0)
187                         {
188                                 callingConvention |= CallingConventions.HasThis;
189                         }
190                         if ((flags & EXPLICITTHIS) != 0)
191                         {
192                                 callingConvention |= CallingConventions.ExplicitThis;
193                         }
194                         Type returnType;
195                         Type[] returnTypeRequiredCustomModifiers;
196                         Type[] returnTypeOptionalCustomModifiers;
197                         Type[] parameterTypes;
198                         Type[][] parameterRequiredCustomModifiers;
199                         Type[][] parameterOptionalCustomModifiers;
200                         int paramCount = br.ReadCompressedInt();
201                         ReadCustomModifiers(module, br, context, out returnTypeRequiredCustomModifiers, out returnTypeOptionalCustomModifiers);
202                         returnType = ReadRetType(module, br, context);
203                         parameterTypes = new Type[paramCount];
204                         parameterRequiredCustomModifiers = null;
205                         parameterOptionalCustomModifiers = null;
206                         for (int i = 0; i < parameterTypes.Length; i++)
207                         {
208                                 if (IsCustomModifier(br.PeekByte()))
209                                 {
210                                         if (parameterOptionalCustomModifiers == null)
211                                         {
212                                                 parameterOptionalCustomModifiers = new Type[parameterTypes.Length][];
213                                                 parameterRequiredCustomModifiers = new Type[parameterTypes.Length][];
214                                         }
215                                         ReadCustomModifiers(module, br, context, out parameterRequiredCustomModifiers[i], out parameterOptionalCustomModifiers[i]);
216                                 }
217                                 parameterTypes[i] = ReadParam(module, br, context);
218                         }
219                         return new PropertySignature(callingConvention, returnType, returnTypeOptionalCustomModifiers, returnTypeRequiredCustomModifiers,
220                                 parameterTypes, parameterOptionalCustomModifiers, parameterRequiredCustomModifiers);
221                 }
222         }
223 }