Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / mscorlib / system / reflection / emit / signaturehelper.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 // <OWNER>Microsoft</OWNER>
7 // 
8
9 namespace System.Reflection.Emit 
10 {
11     using System.Text;
12     using System;
13     using System.Diagnostics.Contracts;
14     using System.Reflection;
15     using System.Runtime.CompilerServices;
16     using System.Runtime.InteropServices;
17     using System.Runtime.Versioning;
18     using System.Security.Permissions;
19     
20     [ClassInterface(ClassInterfaceType.None)]
21     [ComDefaultInterface(typeof(_SignatureHelper))]
22 [System.Runtime.InteropServices.ComVisible(true)]
23     public sealed class SignatureHelper : _SignatureHelper
24     {
25         #region Consts Fields
26         private const int NO_SIZE_IN_SIG = -1;
27         #endregion
28     
29         #region Static Members
30         [System.Security.SecuritySafeCritical]  // auto-generated
31         public static SignatureHelper GetMethodSigHelper(Module mod, Type returnType, Type[] parameterTypes)
32         {
33             return GetMethodSigHelper(mod, CallingConventions.Standard, returnType, null, null, parameterTypes, null, null);
34         }
35
36         [System.Security.SecurityCritical]  // auto-generated
37         internal static SignatureHelper GetMethodSigHelper(Module mod, CallingConventions callingConvention, Type returnType, int cGenericParam)
38         {
39             return GetMethodSigHelper(mod, callingConvention, cGenericParam, returnType, null, null, null, null, null);
40         }
41         
42         [System.Security.SecuritySafeCritical]  // auto-generated
43         public static SignatureHelper GetMethodSigHelper(Module mod, CallingConventions callingConvention, Type returnType)
44         {
45             return GetMethodSigHelper(mod, callingConvention, returnType, null, null, null, null, null);
46         }
47
48         internal static SignatureHelper GetMethodSpecSigHelper(Module scope, Type[] inst)
49         {
50             SignatureHelper sigHelp = new SignatureHelper(scope, MdSigCallingConvention.GenericInst);
51             sigHelp.AddData(inst.Length);
52             foreach(Type t in inst)
53                 sigHelp.AddArgument(t);
54             return sigHelp;
55         }
56         
57         [System.Security.SecurityCritical]  // auto-generated
58         internal static SignatureHelper GetMethodSigHelper(
59             Module scope, CallingConventions callingConvention,
60             Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers,
61             Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
62         {
63             return GetMethodSigHelper(scope, callingConvention, 0, returnType, requiredReturnTypeCustomModifiers, 
64                 optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
65         }
66
67         [System.Security.SecurityCritical]  // auto-generated
68         internal static SignatureHelper GetMethodSigHelper(
69             Module scope, CallingConventions callingConvention, int cGenericParam,
70             Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers,
71             Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
72         {
73             SignatureHelper sigHelp;
74             MdSigCallingConvention intCall;
75                 
76             if (returnType == null)
77             {
78                 returnType = typeof(void);
79             }            
80
81             intCall = MdSigCallingConvention.Default;
82
83             if ((callingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs)
84                 intCall = MdSigCallingConvention.Vararg;
85
86             if (cGenericParam > 0)
87             {
88                 intCall |= MdSigCallingConvention.Generic;
89             }
90
91             if ((callingConvention & CallingConventions.HasThis) == CallingConventions.HasThis)
92                 intCall |= MdSigCallingConvention.HasThis;
93
94             sigHelp = new SignatureHelper(scope, intCall, cGenericParam, returnType, 
95                                             requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers);            
96             sigHelp.AddArguments(parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
97
98             return sigHelp;
99         }
100
101         [System.Security.SecuritySafeCritical]  // auto-generated
102         public static SignatureHelper GetMethodSigHelper(Module mod, CallingConvention unmanagedCallConv, Type returnType)
103         {
104             SignatureHelper sigHelp;
105             MdSigCallingConvention intCall;
106                 
107             if (returnType == null)
108                 returnType = typeof(void);
109
110             if (unmanagedCallConv == CallingConvention.Cdecl)
111             {
112                 intCall = MdSigCallingConvention.C;
113             }
114             else if (unmanagedCallConv == CallingConvention.StdCall || unmanagedCallConv == CallingConvention.Winapi)
115             {
116                 intCall = MdSigCallingConvention.StdCall;
117             }
118             else if (unmanagedCallConv == CallingConvention.ThisCall)
119             {
120                 intCall = MdSigCallingConvention.ThisCall;
121             }
122             else if (unmanagedCallConv == CallingConvention.FastCall)
123             {
124                 intCall = MdSigCallingConvention.FastCall;
125             }
126             else
127             {
128                 throw new ArgumentException(Environment.GetResourceString("Argument_UnknownUnmanagedCallConv"), "unmanagedCallConv");                          
129             }
130             
131             sigHelp = new SignatureHelper(mod, intCall, returnType, null, null);
132             
133             return sigHelp;
134         }
135
136         public static SignatureHelper GetLocalVarSigHelper()
137         {                                                   
138             return GetLocalVarSigHelper(null);
139         }
140         
141         public static SignatureHelper GetMethodSigHelper(CallingConventions callingConvention, Type returnType)
142         {
143             return GetMethodSigHelper(null, callingConvention, returnType);
144         }
145
146         public static SignatureHelper GetMethodSigHelper(CallingConvention unmanagedCallingConvention, Type returnType)
147         {
148             return GetMethodSigHelper(null, unmanagedCallingConvention, returnType);
149         }
150
151         public static SignatureHelper GetLocalVarSigHelper(Module mod)
152         {
153             return new SignatureHelper(mod, MdSigCallingConvention.LocalSig);
154         }
155         
156         public static SignatureHelper GetFieldSigHelper(Module mod)
157         {
158             return new SignatureHelper(mod, MdSigCallingConvention.Field);
159         }
160     
161         public static SignatureHelper GetPropertySigHelper(Module mod, Type returnType, Type[] parameterTypes)
162         {
163             return GetPropertySigHelper(mod, returnType, null, null, parameterTypes, null, null);
164         }
165
166         public static SignatureHelper GetPropertySigHelper(Module mod, 
167             Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, 
168             Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
169         {
170             return GetPropertySigHelper(mod, (CallingConventions)0, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, 
171                 parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
172         }
173         [System.Security.SecuritySafeCritical]  // auto-generated
174         public static SignatureHelper GetPropertySigHelper(Module mod, CallingConventions callingConvention,
175             Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, 
176             Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
177         {
178             SignatureHelper sigHelp;
179                 
180             if (returnType == null)
181             {
182                 returnType = typeof(void);
183             }            
184
185             MdSigCallingConvention intCall = MdSigCallingConvention.Property;
186
187             if ((callingConvention & CallingConventions.HasThis) == CallingConventions.HasThis)
188                 intCall |= MdSigCallingConvention.HasThis;
189
190             sigHelp = new SignatureHelper(mod, intCall, 
191                 returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers);
192             sigHelp.AddArguments(parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
193
194             return sigHelp;
195         }
196         
197         [System.Security.SecurityCritical]  // auto-generated
198         internal static SignatureHelper GetTypeSigToken(Module mod, Type type)
199         {
200             if (mod == null)
201                 throw new ArgumentNullException("module");
202
203             if (type == null)
204                 throw new ArgumentNullException("type");
205
206             return new SignatureHelper(mod, type);
207         }
208         #endregion
209
210         #region Private Data Members
211         private byte[] m_signature;
212         private int m_currSig; // index into m_signature buffer for next available byte
213         private int m_sizeLoc; // index into m_signature buffer to put m_argCount (will be NO_SIZE_IN_SIG if no arg count is needed)
214         private ModuleBuilder m_module;
215         private bool m_sigDone;
216         private int m_argCount; // tracking number of arguments in the signature
217         #endregion
218
219         #region Constructor
220         private SignatureHelper(Module mod, MdSigCallingConvention callingConvention)
221         {
222             // Use this constructor to instantiate a local var sig  or Field where return type is not applied.
223             Init(mod, callingConvention);
224         }
225
226         [System.Security.SecurityCritical]  // auto-generated
227         private SignatureHelper(Module mod, MdSigCallingConvention callingConvention, int cGenericParameters,
228             Type returnType, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
229         {
230             // Use this constructor to instantiate a any signatures that will require a return type.
231             Init(mod, callingConvention, cGenericParameters);
232
233             if (callingConvention == MdSigCallingConvention.Field) 
234                 throw new ArgumentException(Environment.GetResourceString("Argument_BadFieldSig"));
235
236             AddOneArgTypeHelper(returnType, requiredCustomModifiers, optionalCustomModifiers);                          
237         }
238
239         [System.Security.SecurityCritical]  // auto-generated
240         private SignatureHelper(Module mod, MdSigCallingConvention callingConvention, 
241             Type returnType, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
242             : this(mod, callingConvention, 0, returnType, requiredCustomModifiers, optionalCustomModifiers)
243         {
244         }
245
246         [System.Security.SecurityCritical]  // auto-generated
247         private SignatureHelper(Module mod, Type type)
248         {
249             Init(mod);
250
251             AddOneArgTypeHelper(type);
252         }
253
254         private void Init(Module mod)
255         {
256             m_signature = new byte[32];
257             m_currSig = 0;
258             m_module = mod as ModuleBuilder;
259             m_argCount = 0;
260             m_sigDone = false;
261             m_sizeLoc = NO_SIZE_IN_SIG;
262
263             if (m_module == null && mod != null) 
264                 throw new ArgumentException(Environment.GetResourceString("NotSupported_MustBeModuleBuilder"));
265         }
266
267         private void Init(Module mod, MdSigCallingConvention callingConvention)
268         {
269             Init(mod, callingConvention, 0);
270         }
271         
272         private void Init(Module mod, MdSigCallingConvention callingConvention, int cGenericParam)
273         {        
274             Init(mod);
275
276             AddData((byte)callingConvention);
277
278             if (callingConvention == MdSigCallingConvention.Field ||
279                 callingConvention == MdSigCallingConvention.GenericInst) 
280             {
281                 m_sizeLoc = NO_SIZE_IN_SIG;
282             } 
283             else 
284             {
285                 if (cGenericParam > 0)
286                     AddData(cGenericParam);
287                 
288                 m_sizeLoc = m_currSig++;
289             }
290         }
291
292         #endregion
293
294         #region Private Members
295         [System.Security.SecurityCritical]  // auto-generated
296         private void AddOneArgTypeHelper(Type argument, bool pinned)
297         {
298             if (pinned)
299                 AddElementType(CorElementType.Pinned);
300
301             AddOneArgTypeHelper(argument);
302         }
303
304         [System.Security.SecurityCritical]  // auto-generated
305         private void AddOneArgTypeHelper(Type clsArgument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
306         {
307             // This function will not increase the argument count. It only fills in bytes 
308             // in the signature based on clsArgument. This helper is called for return type.
309
310             Contract.Requires(clsArgument != null);
311             Contract.Requires((optionalCustomModifiers == null && requiredCustomModifiers == null) || !clsArgument.ContainsGenericParameters);
312
313             if (optionalCustomModifiers != null)
314             {
315                 for (int i = 0; i < optionalCustomModifiers.Length; i++)
316                 {
317                     Type t = optionalCustomModifiers[i];
318
319                     if (t == null)
320                         throw new ArgumentNullException("optionalCustomModifiers");
321
322                     if (t.HasElementType)
323                         throw new ArgumentException(Environment.GetResourceString("Argument_ArraysInvalid"), "optionalCustomModifiers");
324
325                     if (t.ContainsGenericParameters)
326                         throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), "optionalCustomModifiers");
327
328                     AddElementType(CorElementType.CModOpt);
329
330                     int token = m_module.GetTypeToken(t).Token;
331                     Contract.Assert(!MetadataToken.IsNullToken(token));
332                     AddToken(token);
333                 }
334             }
335
336             if (requiredCustomModifiers != null)
337             {
338                 for (int i = 0; i < requiredCustomModifiers.Length; i++)
339                 {
340                     Type t = requiredCustomModifiers[i];
341
342                     if (t == null)
343                         throw new ArgumentNullException("requiredCustomModifiers");
344
345                     if (t.HasElementType)
346                         throw new ArgumentException(Environment.GetResourceString("Argument_ArraysInvalid"), "requiredCustomModifiers");
347
348                     if (t.ContainsGenericParameters)
349                         throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), "requiredCustomModifiers");
350
351                     AddElementType(CorElementType.CModReqd);
352
353                     int token = m_module.GetTypeToken(t).Token;
354                     Contract.Assert(!MetadataToken.IsNullToken(token));
355                     AddToken(token);
356                 }
357             }
358
359             AddOneArgTypeHelper(clsArgument);
360         }
361
362         [System.Security.SecurityCritical]  // auto-generated
363         private void AddOneArgTypeHelper(Type clsArgument) { AddOneArgTypeHelperWorker(clsArgument, false); }
364         [System.Security.SecurityCritical]  // auto-generated
365         private void AddOneArgTypeHelperWorker(Type clsArgument, bool lastWasGenericInst)
366         {
367             if (clsArgument.IsGenericParameter)
368             {
369                 if (clsArgument.DeclaringMethod != null)
370                     AddElementType(CorElementType.MVar);
371                 else
372                     AddElementType(CorElementType.Var);
373
374                 AddData(clsArgument.GenericParameterPosition);
375             }
376             else if (clsArgument.IsGenericType && (!clsArgument.IsGenericTypeDefinition || !lastWasGenericInst))
377             {
378                 AddElementType(CorElementType.GenericInst);
379
380                 AddOneArgTypeHelperWorker(clsArgument.GetGenericTypeDefinition(), true);
381
382                 Type[] args = clsArgument.GetGenericArguments();
383
384                 AddData(args.Length);
385
386                 foreach (Type t in args)
387                     AddOneArgTypeHelper(t);
388             }
389             else if (clsArgument is TypeBuilder)
390             {
391                 TypeBuilder clsBuilder = (TypeBuilder)clsArgument;
392                 TypeToken tkType;
393
394                 if (clsBuilder.Module.Equals(m_module))
395                 {
396                     tkType = clsBuilder.TypeToken;
397                 }
398                 else
399                 {
400                     tkType = m_module.GetTypeToken(clsArgument);
401                 }
402
403                 if (clsArgument.IsValueType)
404                 {
405                     InternalAddTypeToken(tkType, CorElementType.ValueType);
406                 }
407                 else
408                 {
409                     InternalAddTypeToken(tkType, CorElementType.Class);
410                 }
411             }
412             else if (clsArgument is EnumBuilder)
413             {
414                 TypeBuilder clsBuilder = ((EnumBuilder)clsArgument).m_typeBuilder;
415                 TypeToken tkType;
416
417                 if (clsBuilder.Module.Equals(m_module))
418                 {
419                     tkType = clsBuilder.TypeToken;
420                 }
421                 else
422                 {
423                     tkType = m_module.GetTypeToken(clsArgument);
424                 }
425
426                 if (clsArgument.IsValueType)
427                 {
428                     InternalAddTypeToken(tkType, CorElementType.ValueType);
429                 }
430                 else
431                 {
432                     InternalAddTypeToken(tkType, CorElementType.Class);
433                 }
434             }
435             else if (clsArgument.IsByRef)
436             {
437                 AddElementType(CorElementType.ByRef);
438                 clsArgument = clsArgument.GetElementType();
439                 AddOneArgTypeHelper(clsArgument);
440             }
441             else if (clsArgument.IsPointer)
442             {
443                 AddElementType(CorElementType.Ptr);
444                 AddOneArgTypeHelper(clsArgument.GetElementType());
445             }
446             else if (clsArgument.IsArray)
447             {
448                 if (clsArgument.IsSzArray)
449                 {
450                     AddElementType(CorElementType.SzArray);
451
452                     AddOneArgTypeHelper(clsArgument.GetElementType());
453                 }
454                 else
455                 {
456                     AddElementType(CorElementType.Array);
457
458                     AddOneArgTypeHelper(clsArgument.GetElementType());
459
460                     // put the rank information
461                     int rank = clsArgument.GetArrayRank();
462                     AddData(rank);     // rank
463                     AddData(0);     // upper bounds
464                     AddData(rank);  // lower bound
465                     for (int i = 0; i < rank; i++)
466                         AddData(0);
467                 }
468             }
469             else
470             {
471                 CorElementType type = CorElementType.Max;
472
473                 if (clsArgument is RuntimeType)
474                 {
475                     type = RuntimeTypeHandle.GetCorElementType((RuntimeType)clsArgument);
476
477                     //GetCorElementType returns CorElementType.Class for both object and string
478                     if (type == CorElementType.Class)
479                     {
480                         if (clsArgument == typeof(object))
481                             type = CorElementType.Object;
482                         else if (clsArgument == typeof(string))
483                             type = CorElementType.String;
484                     }
485                 }
486
487                 if (IsSimpleType(type))
488                 {
489                     AddElementType(type);
490                 }
491                 else if (m_module == null)
492                 {
493                     InternalAddRuntimeType(clsArgument);
494                 }
495                 else if (clsArgument.IsValueType)
496                 {
497                     InternalAddTypeToken(m_module.GetTypeToken(clsArgument), CorElementType.ValueType);
498                 }
499                 else
500                 {
501                     InternalAddTypeToken(m_module.GetTypeToken(clsArgument), CorElementType.Class);
502                 }
503             }
504         }
505     
506         private void AddData(int data)
507         {
508             // A managed representation of CorSigCompressData; 
509
510             if (m_currSig + 4 > m_signature.Length)
511             {
512                 m_signature = ExpandArray(m_signature);
513             }
514     
515             if (data <= 0x7F)
516             {
517                 m_signature[m_currSig++] = (byte)(data & 0xFF);
518             } 
519             else if (data <= 0x3FFF)
520             {
521                 m_signature[m_currSig++] = (byte)((data >>8) | 0x80);
522                 m_signature[m_currSig++] = (byte)(data & 0xFF);
523             } 
524             else if (data <= 0x1FFFFFFF)
525             {
526                 m_signature[m_currSig++] = (byte)((data >>24) | 0xC0);
527                 m_signature[m_currSig++] = (byte)((data >>16) & 0xFF);
528                 m_signature[m_currSig++] = (byte)((data >>8) & 0xFF);
529                 m_signature[m_currSig++] = (byte)((data) & 0xFF);
530             } 
531             else
532             {
533                 throw new ArgumentException(Environment.GetResourceString("Argument_LargeInteger"));
534             }            
535             
536         }
537
538         private void AddData(uint data)
539         {
540             if (m_currSig + 4 > m_signature.Length)
541             {
542                 m_signature = ExpandArray(m_signature);
543             }
544
545             m_signature[m_currSig++] = (byte)((data)     & 0xFF);
546             m_signature[m_currSig++] = (byte)((data>>8)  & 0xFF);
547             m_signature[m_currSig++] = (byte)((data>>16) & 0xFF);
548             m_signature[m_currSig++] = (byte)((data>>24) & 0xFF);
549         }
550         
551         private void AddData(ulong data)
552         {
553             if (m_currSig + 8 > m_signature.Length)
554             {
555                 m_signature = ExpandArray(m_signature);
556             }
557
558             m_signature[m_currSig++] = (byte)((data)     & 0xFF);
559             m_signature[m_currSig++] = (byte)((data>>8)  & 0xFF);
560             m_signature[m_currSig++] = (byte)((data>>16) & 0xFF);
561             m_signature[m_currSig++] = (byte)((data>>24) & 0xFF);
562             m_signature[m_currSig++] = (byte)((data>>32) & 0xFF);
563             m_signature[m_currSig++] = (byte)((data>>40) & 0xFF);
564             m_signature[m_currSig++] = (byte)((data>>48) & 0xFF);
565             m_signature[m_currSig++] = (byte)((data>>56) & 0xFF);
566         }
567         
568         private void AddElementType(CorElementType cvt)
569         {
570             // Adds an element to the signature.  A managed represenation of CorSigCompressElement
571             if (m_currSig + 1 > m_signature.Length) 
572                 m_signature = ExpandArray(m_signature);
573
574             m_signature[m_currSig++] = (byte)cvt;
575         }
576     
577         private void AddToken(int token) 
578         {
579             // A managed represenation of CompressToken
580             // Pulls the token appart to get a rid, adds some appropriate bits
581             // to the token and then adds this to the signature.
582
583             int rid =  (token & 0x00FFFFFF); //This is RidFromToken;
584             MetadataTokenType type = (MetadataTokenType)(token & unchecked((int)0xFF000000)); //This is TypeFromToken;
585     
586             if (rid > 0x3FFFFFF) 
587             {
588                 // token is too big to be compressed    
589                 throw new ArgumentException(Environment.GetResourceString("Argument_LargeInteger"));
590             }
591     
592             rid = (rid << 2);   
593             
594             // TypeDef is encoded with low bits 00  
595             // TypeRef is encoded with low bits 01  
596             // TypeSpec is encoded with low bits 10    
597             if (type == MetadataTokenType.TypeRef) 
598             { 
599                 //if type is mdtTypeRef
600                 rid|=0x1;
601             } 
602             else if (type == MetadataTokenType.TypeSpec) 
603             { 
604                 //if type is mdtTypeSpec
605                 rid|=0x2;
606             }
607     
608             AddData(rid);
609         }
610     
611         private void InternalAddTypeToken(TypeToken clsToken, CorElementType CorType)
612         {
613             // Add a type token into signature. CorType will be either CorElementType.Class or CorElementType.ValueType
614             AddElementType(CorType);
615             AddToken(clsToken.Token);
616         }
617     
618         [System.Security.SecurityCritical]  // auto-generated
619         private unsafe void InternalAddRuntimeType(Type type)
620         {
621             // Add a runtime type into the signature. 
622
623             AddElementType(CorElementType.Internal);
624
625             IntPtr handle = type.GetTypeHandleInternal().Value;
626
627             // Internal types must have their pointer written into the signature directly (we don't
628             // want to convert to little-endian format on big-endian machines because the value is
629             // going to be extracted and used directly as a pointer (and only within this process)).
630
631             if (m_currSig + sizeof(void*) > m_signature.Length)
632                 m_signature = ExpandArray(m_signature);
633
634             byte *phandle = (byte*)&handle;
635             for (int i = 0; i < sizeof(void*); i++)
636                 m_signature[m_currSig++] = phandle[i];
637         }
638     
639         private byte[] ExpandArray(byte[] inArray)
640         {
641             // Expand the signature buffer size
642             return ExpandArray(inArray, inArray.Length * 2);
643         }
644
645         private byte[] ExpandArray(byte[] inArray, int requiredLength)
646         {
647             // Expand the signature buffer size
648
649             if (requiredLength < inArray.Length) 
650                 requiredLength = inArray.Length*2;
651
652             byte[] outArray = new byte[requiredLength];
653             Array.Copy(inArray, outArray, inArray.Length);
654             return outArray;
655         }
656     
657         private void IncrementArgCounts()
658         {
659             if (m_sizeLoc == NO_SIZE_IN_SIG) 
660             { 
661                 //We don't have a size if this is a field.
662                 return;
663             }
664
665             m_argCount++;
666         }
667     
668         private void SetNumberOfSignatureElements(bool forceCopy)
669         {
670             // For most signatures, this will set the number of elements in a byte which we have reserved for it.
671             // However, if we have a field signature, we don't set the length and return.
672             // If we have a signature with more than 128 arguments, we can't just set the number of elements,
673             // we actually have to allocate more space (e.g. shift everything in the array one or more spaces to the
674             // right.  We do this by making a copy of the array and leaving the correct number of blanks.  This new
675             // array is now set to be m_signature and we use the AddData method to set the number of elements properly.
676             // The forceCopy argument can be used to force SetNumberOfSignatureElements to make a copy of
677             // the array.  This is useful for GetSignature which promises to trim the array to be the correct size anyway.
678
679             byte[] temp;
680             int newSigSize;
681             int currSigHolder = m_currSig;
682     
683             if (m_sizeLoc == NO_SIZE_IN_SIG) 
684                 return;
685     
686             //If we have fewer than 128 arguments and we haven't been told to copy the
687             //array, we can just set the appropriate bit and return.
688             if (m_argCount < 0x80 && !forceCopy) 
689             {
690                 m_signature[m_sizeLoc] = (byte)m_argCount;
691                 return;
692             } 
693     
694             //We need to have more bytes for the size.  Figure out how many bytes here.
695             //Since we need to copy anyway, we're just going to take the cost of doing a
696             //new allocation.
697             if (m_argCount < 0x80)
698             {
699                 newSigSize = 1;
700             }
701             else if (m_argCount < 0x4000)
702             {
703                 newSigSize = 2;
704             }
705             else
706             {
707                 newSigSize = 4;
708             }
709             
710             //Allocate the new array.
711             temp = new byte[m_currSig + newSigSize - 1];
712     
713             //Copy the calling convention.  The calling convention is always just one byte
714             //so we just copy that byte.  Then copy the rest of the array, shifting everything
715             //to make room for the new number of elements.
716             temp[0] = m_signature[0];
717             Array.Copy(m_signature, m_sizeLoc + 1, temp, m_sizeLoc + newSigSize, currSigHolder - (m_sizeLoc + 1));
718             m_signature = temp;
719             
720             //Use the AddData method to add the number of elements appropriately compressed.
721             m_currSig = m_sizeLoc;
722             AddData(m_argCount);
723             m_currSig = currSigHolder + (newSigSize - 1);
724         }
725     
726         #endregion
727
728         #region Internal Members
729         internal int ArgumentCount
730         { 
731             get 
732             { 
733                 return m_argCount; 
734             } 
735         }
736
737         internal static bool IsSimpleType(CorElementType type)
738         {
739             if (type <= CorElementType.String) 
740                 return true;
741
742             if (type == CorElementType.TypedByRef || type == CorElementType.I || type == CorElementType.U || type == CorElementType.Object) 
743                 return true;
744
745             return false;
746         }
747     
748         internal byte[] InternalGetSignature(out int length)
749         {
750             // An internal method to return the signature.  Does not trim the
751             // array, but passes out the length of the array in an out parameter.
752             // This is the actual array -- not a copy -- so the callee must agree
753             // to not copy it.
754             //
755             // param length : an out param indicating the length of the array.
756             // return : A reference to the internal ubyte array.
757     
758             if (!m_sigDone)
759             {
760                 m_sigDone = true;
761
762                 // If we have more than 128 variables, we can't just set the length, we need 
763                 // to compress it.  Unfortunately, this means that we need to copy the entire 
764                 // array.  Bummer, eh?
765                 SetNumberOfSignatureElements(false);
766             }
767     
768             length = m_currSig;
769             return m_signature;
770         }
771     
772          
773          
774          
775         internal byte[] InternalGetSignatureArray()
776         {
777             int argCount = m_argCount; 
778             int currSigLength = m_currSig;
779             int newSigSize = currSigLength;
780     
781             //Allocate the new array.
782             if (argCount < 0x7F)
783                 newSigSize += 1;
784             else if (argCount < 0x3FFF)
785                 newSigSize += 2;
786             else
787                 newSigSize += 4;
788             byte[] temp = new byte[newSigSize];
789
790             // copy the sig
791             int sigCopyIndex = 0;
792             // calling convention
793             temp[sigCopyIndex++] = m_signature[0];
794             // arg size
795             if (argCount <= 0x7F)
796                 temp[sigCopyIndex++] = (byte)(argCount & 0xFF);
797             else if (argCount <= 0x3FFF)
798             {
799                 temp[sigCopyIndex++] = (byte)((argCount >>8) | 0x80);
800                 temp[sigCopyIndex++] = (byte)(argCount & 0xFF);
801             } 
802             else if (argCount <= 0x1FFFFFFF)
803             {
804                 temp[sigCopyIndex++] = (byte)((argCount >>24) | 0xC0);
805                 temp[sigCopyIndex++] = (byte)((argCount >>16) & 0xFF);
806                 temp[sigCopyIndex++] = (byte)((argCount >>8) & 0xFF);
807                 temp[sigCopyIndex++] = (byte)((argCount) & 0xFF);
808             } 
809             else
810                 throw new ArgumentException(Environment.GetResourceString("Argument_LargeInteger"));
811             // copy the sig part of the sig
812             Array.Copy(m_signature, 2, temp, sigCopyIndex, currSigLength - 2);
813             // mark the end of sig
814             temp[newSigSize - 1] = (byte)CorElementType.End;
815     
816             return temp;
817         }
818     
819         #endregion
820
821         #region Public Methods
822         public void AddArgument(Type clsArgument)
823         {
824             AddArgument(clsArgument, null, null);
825         }
826
827         [System.Security.SecuritySafeCritical]  // auto-generated
828         public void AddArgument(Type argument, bool pinned)
829         {
830             if (argument == null)
831                 throw new ArgumentNullException("argument");
832
833             IncrementArgCounts();
834             AddOneArgTypeHelper(argument, pinned);
835         }
836         
837         public void AddArguments(Type[] arguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
838         {
839             if (requiredCustomModifiers != null && (arguments == null || requiredCustomModifiers.Length != arguments.Length))
840                 throw new ArgumentException(Environment.GetResourceString("Argument_MismatchedArrays", "requiredCustomModifiers", "arguments"));
841
842             if (optionalCustomModifiers != null && (arguments == null || optionalCustomModifiers.Length != arguments.Length))
843                 throw new ArgumentException(Environment.GetResourceString("Argument_MismatchedArrays", "optionalCustomModifiers", "arguments"));
844
845             if (arguments != null)
846             {
847                 for (int i =0; i < arguments.Length; i++)
848                 {
849                     AddArgument(arguments[i], 
850                         requiredCustomModifiers == null ? null : requiredCustomModifiers[i], 
851                         optionalCustomModifiers == null ? null : optionalCustomModifiers[i]);
852                 }
853             }
854         }
855
856         [System.Security.SecuritySafeCritical]  // auto-generated
857         public void AddArgument(Type argument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
858         {
859             if (m_sigDone)
860                 throw new ArgumentException(Environment.GetResourceString("Argument_SigIsFinalized"));
861     
862             if (argument == null)
863                 throw new ArgumentNullException("argument");
864
865             IncrementArgCounts();
866     
867             // Add an argument to the signature. Takes a Type and determines whether it
868             // is one of the primitive types of which we have special knowledge or a more
869             // general class.  In the former case, we only add the appropriate short cut encoding, 
870             // otherwise we will calculate proper description for the type.
871             AddOneArgTypeHelper(argument, requiredCustomModifiers, optionalCustomModifiers);
872         }
873
874         public void AddSentinel()
875         {
876             AddElementType(CorElementType.Sentinel);
877         }
878
879         public override bool Equals(Object obj)
880         {
881             if (!(obj is SignatureHelper)) 
882             {
883                 return false;
884             }
885             
886             SignatureHelper temp = (SignatureHelper)obj;
887             
888             if ( !temp.m_module.Equals(m_module) || temp.m_currSig!=m_currSig || temp.m_sizeLoc!=m_sizeLoc || temp.m_sigDone !=m_sigDone )
889             {
890                 return false;
891             }
892             
893             for (int i=0; i<m_currSig; i++) 
894             {
895                 if (m_signature[i]!=temp.m_signature[i]) 
896                     return false;
897             }
898             return true;
899         }
900     
901         public override int GetHashCode()
902         {
903             // Start the hash code with the hash code of the module and the values of the member variables.
904             int HashCode = m_module.GetHashCode() + m_currSig + m_sizeLoc;
905
906             // Add one if the sig is done.
907             if (m_sigDone)
908                 HashCode += 1;
909
910             // Then add the hash code of all the arguments.
911             for (int i=0; i < m_currSig; i++) 
912                 HashCode += m_signature[i].GetHashCode();
913
914             return HashCode;
915         }
916
917         public byte[] GetSignature()
918         {
919             return GetSignature(false);
920         }
921     
922         internal byte[] GetSignature(bool appendEndOfSig)
923         {
924             // Chops the internal signature to the appropriate length.  Adds the 
925             // end token to the signature and marks the signature as finished so that
926             // no further tokens can be added. Return the full signature in a trimmed array.
927             if (!m_sigDone) 
928             {
929                 if (appendEndOfSig) 
930                     AddElementType(CorElementType.End);
931                 SetNumberOfSignatureElements(true);
932                 m_sigDone = true;
933             }
934     
935             // This case will only happen if the user got the signature through 
936             // InternalGetSignature first and then called GetSignature.
937             if (m_signature.Length > m_currSig) 
938             {
939                 byte[] temp = new byte[m_currSig];
940                 Array.Copy(m_signature, temp, m_currSig);
941                 m_signature = temp;
942             }
943
944             return m_signature;
945         }
946     
947         public override String ToString()
948         {
949             StringBuilder sb = new StringBuilder();
950             sb.Append("Length: " + m_currSig + Environment.NewLine);
951
952             if (m_sizeLoc != -1)
953             {
954                 sb.Append("Arguments: " + m_signature[m_sizeLoc] + Environment.NewLine);
955             }
956             else
957             {
958                 sb.Append("Field Signature" + Environment.NewLine);
959             }
960
961             sb.Append("Signature: " + Environment.NewLine);
962             for (int i=0; i<=m_currSig; i++) 
963             {
964                 sb.Append(m_signature[i] + "  ");
965             }
966
967             sb.Append(Environment.NewLine);
968             return sb.ToString();
969         }
970         
971         #endregion
972
973 #if !FEATURE_CORECLR
974         void _SignatureHelper.GetTypeInfoCount(out uint pcTInfo)
975         {
976             throw new NotImplementedException();
977         }
978
979         void _SignatureHelper.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
980         {
981             throw new NotImplementedException();
982         }
983
984         void _SignatureHelper.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
985         {
986             throw new NotImplementedException();
987         }
988
989         void _SignatureHelper.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
990         {
991             throw new NotImplementedException();
992         }
993 #endif
994
995     }
996 }
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021