Merge pull request #200 from ch5oh/master
[mono.git] / mcs / class / IKVM.Reflection / PropertySignature.cs
1 /*
2   Copyright (C) 2009-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.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[] parameterTypes;
39                 private readonly PackedCustomModifiers customModifiers;
40
41                 internal static PropertySignature Create(CallingConventions callingConvention, Type propertyType, Type[] parameterTypes, PackedCustomModifiers customModifiers)
42                 {
43                         return new PropertySignature(callingConvention, propertyType, Util.Copy(parameterTypes), customModifiers);
44                 }
45
46                 private PropertySignature(CallingConventions callingConvention, Type propertyType, Type[] parameterTypes, PackedCustomModifiers customModifiers)
47                 {
48                         this.callingConvention = callingConvention;
49                         this.propertyType = propertyType;
50                         this.parameterTypes = parameterTypes;
51                         this.customModifiers = customModifiers;
52                 }
53
54                 public override bool Equals(object obj)
55                 {
56                         PropertySignature other = obj as PropertySignature;
57                         return other != null
58                                 && other.propertyType.Equals(propertyType)
59                                 && other.customModifiers.Equals(customModifiers);
60                 }
61
62                 public override int GetHashCode()
63                 {
64                         return propertyType.GetHashCode() ^ customModifiers.GetHashCode();
65                 }
66
67                 internal int ParameterCount
68                 {
69                         get { return parameterTypes.Length; }
70                 }
71
72                 internal bool HasThis
73                 {
74                         set
75                         {
76                                 if (value)
77                                 {
78                                         callingConvention |= CallingConventions.HasThis;
79                                 }
80                                 else
81                                 {
82                                         callingConvention &= ~CallingConventions.HasThis;
83                                 }
84                         }
85                 }
86
87                 internal Type PropertyType
88                 {
89                         get { return propertyType; }
90                 }
91
92                 internal CustomModifiers GetCustomModifiers()
93                 {
94                         return customModifiers.GetReturnTypeCustomModifiers();
95                 }
96
97                 internal PropertySignature ExpandTypeParameters(Type declaringType)
98                 {
99                         return new PropertySignature(
100                                 callingConvention,
101                                 propertyType.BindTypeParameters(declaringType),
102                                 BindTypeParameters(declaringType, parameterTypes),
103                                 customModifiers.Bind(declaringType));
104                 }
105
106                 internal override void WriteSig(ModuleBuilder module, ByteBuffer bb)
107                 {
108                         byte flags = PROPERTY;
109                         if ((callingConvention & CallingConventions.HasThis) != 0)
110                         {
111                                 flags |= HASTHIS;
112                         }
113                         if ((callingConvention & CallingConventions.ExplicitThis) != 0)
114                         {
115                                 flags |= EXPLICITTHIS;
116                         }
117                         if ((callingConvention & CallingConventions.VarArgs) != 0)
118                         {
119                                 flags |= VARARG;
120                         }
121                         bb.Write(flags);
122                         bb.WriteCompressedInt(parameterTypes == null ? 0 : parameterTypes.Length);
123                         WriteCustomModifiers(module, bb, customModifiers.GetReturnTypeCustomModifiers());
124                         WriteType(module, bb, propertyType);
125                         if (parameterTypes != null)
126                         {
127                                 for (int i = 0; i < parameterTypes.Length; i++)
128                                 {
129                                         WriteCustomModifiers(module, bb, customModifiers.GetParameterCustomModifiers(i));
130                                         WriteType(module, bb, parameterTypes[i]);
131                                 }
132                         }
133                 }
134
135                 internal Type GetParameter(int parameter)
136                 {
137                         return parameterTypes[parameter];
138                 }
139
140                 internal CustomModifiers GetParameterCustomModifiers(int parameter)
141                 {
142                         return customModifiers.GetParameterCustomModifiers(parameter);
143                 }
144
145                 internal CallingConventions CallingConvention
146                 {
147                         get { return callingConvention; }
148                 }
149
150                 internal static PropertySignature ReadSig(ModuleReader module, ByteReader br, IGenericContext context)
151                 {
152                         byte flags = br.ReadByte();
153                         if ((flags & PROPERTY) == 0)
154                         {
155                                 throw new BadImageFormatException();
156                         }
157                         CallingConventions callingConvention = CallingConventions.Standard;
158                         if ((flags & HASTHIS) != 0)
159                         {
160                                 callingConvention |= CallingConventions.HasThis;
161                         }
162                         if ((flags & EXPLICITTHIS) != 0)
163                         {
164                                 callingConvention |= CallingConventions.ExplicitThis;
165                         }
166                         Type returnType;
167                         Type[] parameterTypes;
168                         int paramCount = br.ReadCompressedInt();
169                         CustomModifiers[] mods = null;
170                         PackedCustomModifiers.Pack(ref mods, 0, CustomModifiers.Read(module, br, context), paramCount + 1);
171                         returnType = ReadRetType(module, br, context);
172                         parameterTypes = new Type[paramCount];
173                         for (int i = 0; i < parameterTypes.Length; i++)
174                         {
175                                 PackedCustomModifiers.Pack(ref mods, i + 1, CustomModifiers.Read(module, br, context), paramCount + 1);
176                                 parameterTypes[i] = ReadParam(module, br, context);
177                         }
178                         return new PropertySignature(callingConvention, returnType, parameterTypes, PackedCustomModifiers.Wrap(mods));
179                 }
180         }
181 }