diff options
Diffstat (limited to 'src/mscorlib/src/System/Reflection/Emit/SignatureHelper.cs')
-rw-r--r-- | src/mscorlib/src/System/Reflection/Emit/SignatureHelper.cs | 1018 |
1 files changed, 1018 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Reflection/Emit/SignatureHelper.cs b/src/mscorlib/src/System/Reflection/Emit/SignatureHelper.cs new file mode 100644 index 0000000000..74f9db9cc0 --- /dev/null +++ b/src/mscorlib/src/System/Reflection/Emit/SignatureHelper.cs @@ -0,0 +1,1018 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +// + +namespace System.Reflection.Emit +{ + using System.Text; + using System; + using System.Diagnostics.Contracts; + using System.Reflection; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Runtime.Versioning; + using System.Security.Permissions; + + [ClassInterface(ClassInterfaceType.None)] + [ComDefaultInterface(typeof(_SignatureHelper))] +[System.Runtime.InteropServices.ComVisible(true)] + public sealed class SignatureHelper : _SignatureHelper + { + #region Consts Fields + private const int NO_SIZE_IN_SIG = -1; + #endregion + + #region Static Members + [System.Security.SecuritySafeCritical] // auto-generated + public static SignatureHelper GetMethodSigHelper(Module mod, Type returnType, Type[] parameterTypes) + { + return GetMethodSigHelper(mod, CallingConventions.Standard, returnType, null, null, parameterTypes, null, null); + } + + [System.Security.SecurityCritical] // auto-generated + internal static SignatureHelper GetMethodSigHelper(Module mod, CallingConventions callingConvention, Type returnType, int cGenericParam) + { + return GetMethodSigHelper(mod, callingConvention, cGenericParam, returnType, null, null, null, null, null); + } + + [System.Security.SecuritySafeCritical] // auto-generated + public static SignatureHelper GetMethodSigHelper(Module mod, CallingConventions callingConvention, Type returnType) + { + return GetMethodSigHelper(mod, callingConvention, returnType, null, null, null, null, null); + } + + internal static SignatureHelper GetMethodSpecSigHelper(Module scope, Type[] inst) + { + SignatureHelper sigHelp = new SignatureHelper(scope, MdSigCallingConvention.GenericInst); + sigHelp.AddData(inst.Length); + foreach(Type t in inst) + sigHelp.AddArgument(t); + return sigHelp; + } + + [System.Security.SecurityCritical] // auto-generated + internal static SignatureHelper GetMethodSigHelper( + Module scope, CallingConventions callingConvention, + Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, + Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers) + { + return GetMethodSigHelper(scope, callingConvention, 0, returnType, requiredReturnTypeCustomModifiers, + optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers); + } + + [System.Security.SecurityCritical] // auto-generated + internal static SignatureHelper GetMethodSigHelper( + Module scope, CallingConventions callingConvention, int cGenericParam, + Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, + Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers) + { + SignatureHelper sigHelp; + MdSigCallingConvention intCall; + + if (returnType == null) + { + returnType = typeof(void); + } + + intCall = MdSigCallingConvention.Default; + + if ((callingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs) + intCall = MdSigCallingConvention.Vararg; + + if (cGenericParam > 0) + { + intCall |= MdSigCallingConvention.Generic; + } + + if ((callingConvention & CallingConventions.HasThis) == CallingConventions.HasThis) + intCall |= MdSigCallingConvention.HasThis; + + sigHelp = new SignatureHelper(scope, intCall, cGenericParam, returnType, + requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers); + sigHelp.AddArguments(parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers); + + return sigHelp; + } + + [System.Security.SecuritySafeCritical] // auto-generated + public static SignatureHelper GetMethodSigHelper(Module mod, CallingConvention unmanagedCallConv, Type returnType) + { + SignatureHelper sigHelp; + MdSigCallingConvention intCall; + + if (returnType == null) + returnType = typeof(void); + + if (unmanagedCallConv == CallingConvention.Cdecl) + { + intCall = MdSigCallingConvention.C; + } + else if (unmanagedCallConv == CallingConvention.StdCall || unmanagedCallConv == CallingConvention.Winapi) + { + intCall = MdSigCallingConvention.StdCall; + } + else if (unmanagedCallConv == CallingConvention.ThisCall) + { + intCall = MdSigCallingConvention.ThisCall; + } + else if (unmanagedCallConv == CallingConvention.FastCall) + { + intCall = MdSigCallingConvention.FastCall; + } + else + { + throw new ArgumentException(Environment.GetResourceString("Argument_UnknownUnmanagedCallConv"), "unmanagedCallConv"); + } + + sigHelp = new SignatureHelper(mod, intCall, returnType, null, null); + + return sigHelp; + } + + public static SignatureHelper GetLocalVarSigHelper() + { + return GetLocalVarSigHelper(null); + } + + public static SignatureHelper GetMethodSigHelper(CallingConventions callingConvention, Type returnType) + { + return GetMethodSigHelper(null, callingConvention, returnType); + } + + public static SignatureHelper GetMethodSigHelper(CallingConvention unmanagedCallingConvention, Type returnType) + { + return GetMethodSigHelper(null, unmanagedCallingConvention, returnType); + } + + public static SignatureHelper GetLocalVarSigHelper(Module mod) + { + return new SignatureHelper(mod, MdSigCallingConvention.LocalSig); + } + + public static SignatureHelper GetFieldSigHelper(Module mod) + { + return new SignatureHelper(mod, MdSigCallingConvention.Field); + } + + public static SignatureHelper GetPropertySigHelper(Module mod, Type returnType, Type[] parameterTypes) + { + return GetPropertySigHelper(mod, returnType, null, null, parameterTypes, null, null); + } + + public static SignatureHelper GetPropertySigHelper(Module mod, + Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, + Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers) + { + return GetPropertySigHelper(mod, (CallingConventions)0, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, + parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers); + } + [System.Security.SecuritySafeCritical] // auto-generated + public static SignatureHelper GetPropertySigHelper(Module mod, CallingConventions callingConvention, + Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, + Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers) + { + SignatureHelper sigHelp; + + if (returnType == null) + { + returnType = typeof(void); + } + + MdSigCallingConvention intCall = MdSigCallingConvention.Property; + + if ((callingConvention & CallingConventions.HasThis) == CallingConventions.HasThis) + intCall |= MdSigCallingConvention.HasThis; + + sigHelp = new SignatureHelper(mod, intCall, + returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers); + sigHelp.AddArguments(parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers); + + return sigHelp; + } + + [System.Security.SecurityCritical] // auto-generated + internal static SignatureHelper GetTypeSigToken(Module mod, Type type) + { + if (mod == null) + throw new ArgumentNullException("module"); + + if (type == null) + throw new ArgumentNullException("type"); + + return new SignatureHelper(mod, type); + } + #endregion + + #region Private Data Members + private byte[] m_signature; + private int m_currSig; // index into m_signature buffer for next available byte + 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) + private ModuleBuilder m_module; + private bool m_sigDone; + private int m_argCount; // tracking number of arguments in the signature + #endregion + + #region Constructor + private SignatureHelper(Module mod, MdSigCallingConvention callingConvention) + { + // Use this constructor to instantiate a local var sig or Field where return type is not applied. + Init(mod, callingConvention); + } + + [System.Security.SecurityCritical] // auto-generated + private SignatureHelper(Module mod, MdSigCallingConvention callingConvention, int cGenericParameters, + Type returnType, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers) + { + // Use this constructor to instantiate a any signatures that will require a return type. + Init(mod, callingConvention, cGenericParameters); + + if (callingConvention == MdSigCallingConvention.Field) + throw new ArgumentException(Environment.GetResourceString("Argument_BadFieldSig")); + + AddOneArgTypeHelper(returnType, requiredCustomModifiers, optionalCustomModifiers); + } + + [System.Security.SecurityCritical] // auto-generated + private SignatureHelper(Module mod, MdSigCallingConvention callingConvention, + Type returnType, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers) + : this(mod, callingConvention, 0, returnType, requiredCustomModifiers, optionalCustomModifiers) + { + } + + [System.Security.SecurityCritical] // auto-generated + private SignatureHelper(Module mod, Type type) + { + Init(mod); + + AddOneArgTypeHelper(type); + } + + private void Init(Module mod) + { + m_signature = new byte[32]; + m_currSig = 0; + m_module = mod as ModuleBuilder; + m_argCount = 0; + m_sigDone = false; + m_sizeLoc = NO_SIZE_IN_SIG; + + if (m_module == null && mod != null) + throw new ArgumentException(Environment.GetResourceString("NotSupported_MustBeModuleBuilder")); + } + + private void Init(Module mod, MdSigCallingConvention callingConvention) + { + Init(mod, callingConvention, 0); + } + + private void Init(Module mod, MdSigCallingConvention callingConvention, int cGenericParam) + { + Init(mod); + + AddData((byte)callingConvention); + + if (callingConvention == MdSigCallingConvention.Field || + callingConvention == MdSigCallingConvention.GenericInst) + { + m_sizeLoc = NO_SIZE_IN_SIG; + } + else + { + if (cGenericParam > 0) + AddData(cGenericParam); + + m_sizeLoc = m_currSig++; + } + } + + #endregion + + #region Private Members + [System.Security.SecurityCritical] // auto-generated + private void AddOneArgTypeHelper(Type argument, bool pinned) + { + if (pinned) + AddElementType(CorElementType.Pinned); + + AddOneArgTypeHelper(argument); + } + + [System.Security.SecurityCritical] // auto-generated + private void AddOneArgTypeHelper(Type clsArgument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers) + { + // This function will not increase the argument count. It only fills in bytes + // in the signature based on clsArgument. This helper is called for return type. + + Contract.Requires(clsArgument != null); + Contract.Requires((optionalCustomModifiers == null && requiredCustomModifiers == null) || !clsArgument.ContainsGenericParameters); + + if (optionalCustomModifiers != null) + { + for (int i = 0; i < optionalCustomModifiers.Length; i++) + { + Type t = optionalCustomModifiers[i]; + + if (t == null) + throw new ArgumentNullException("optionalCustomModifiers"); + + if (t.HasElementType) + throw new ArgumentException(Environment.GetResourceString("Argument_ArraysInvalid"), "optionalCustomModifiers"); + + if (t.ContainsGenericParameters) + throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), "optionalCustomModifiers"); + + AddElementType(CorElementType.CModOpt); + + int token = m_module.GetTypeToken(t).Token; + Contract.Assert(!MetadataToken.IsNullToken(token)); + AddToken(token); + } + } + + if (requiredCustomModifiers != null) + { + for (int i = 0; i < requiredCustomModifiers.Length; i++) + { + Type t = requiredCustomModifiers[i]; + + if (t == null) + throw new ArgumentNullException("requiredCustomModifiers"); + + if (t.HasElementType) + throw new ArgumentException(Environment.GetResourceString("Argument_ArraysInvalid"), "requiredCustomModifiers"); + + if (t.ContainsGenericParameters) + throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), "requiredCustomModifiers"); + + AddElementType(CorElementType.CModReqd); + + int token = m_module.GetTypeToken(t).Token; + Contract.Assert(!MetadataToken.IsNullToken(token)); + AddToken(token); + } + } + + AddOneArgTypeHelper(clsArgument); + } + + [System.Security.SecurityCritical] // auto-generated + private void AddOneArgTypeHelper(Type clsArgument) { AddOneArgTypeHelperWorker(clsArgument, false); } + [System.Security.SecurityCritical] // auto-generated + private void AddOneArgTypeHelperWorker(Type clsArgument, bool lastWasGenericInst) + { + if (clsArgument.IsGenericParameter) + { + if (clsArgument.DeclaringMethod != null) + AddElementType(CorElementType.MVar); + else + AddElementType(CorElementType.Var); + + AddData(clsArgument.GenericParameterPosition); + } + else if (clsArgument.IsGenericType && (!clsArgument.IsGenericTypeDefinition || !lastWasGenericInst)) + { + AddElementType(CorElementType.GenericInst); + + AddOneArgTypeHelperWorker(clsArgument.GetGenericTypeDefinition(), true); + + Type[] args = clsArgument.GetGenericArguments(); + + AddData(args.Length); + + foreach (Type t in args) + AddOneArgTypeHelper(t); + } + else if (clsArgument is TypeBuilder) + { + TypeBuilder clsBuilder = (TypeBuilder)clsArgument; + TypeToken tkType; + + if (clsBuilder.Module.Equals(m_module)) + { + tkType = clsBuilder.TypeToken; + } + else + { + tkType = m_module.GetTypeToken(clsArgument); + } + + if (clsArgument.IsValueType) + { + InternalAddTypeToken(tkType, CorElementType.ValueType); + } + else + { + InternalAddTypeToken(tkType, CorElementType.Class); + } + } + else if (clsArgument is EnumBuilder) + { + TypeBuilder clsBuilder = ((EnumBuilder)clsArgument).m_typeBuilder; + TypeToken tkType; + + if (clsBuilder.Module.Equals(m_module)) + { + tkType = clsBuilder.TypeToken; + } + else + { + tkType = m_module.GetTypeToken(clsArgument); + } + + if (clsArgument.IsValueType) + { + InternalAddTypeToken(tkType, CorElementType.ValueType); + } + else + { + InternalAddTypeToken(tkType, CorElementType.Class); + } + } + else if (clsArgument.IsByRef) + { + AddElementType(CorElementType.ByRef); + clsArgument = clsArgument.GetElementType(); + AddOneArgTypeHelper(clsArgument); + } + else if (clsArgument.IsPointer) + { + AddElementType(CorElementType.Ptr); + AddOneArgTypeHelper(clsArgument.GetElementType()); + } + else if (clsArgument.IsArray) + { + if (clsArgument.IsSzArray) + { + AddElementType(CorElementType.SzArray); + + AddOneArgTypeHelper(clsArgument.GetElementType()); + } + else + { + AddElementType(CorElementType.Array); + + AddOneArgTypeHelper(clsArgument.GetElementType()); + + // put the rank information + int rank = clsArgument.GetArrayRank(); + AddData(rank); // rank + AddData(0); // upper bounds + AddData(rank); // lower bound + for (int i = 0; i < rank; i++) + AddData(0); + } + } + else + { + CorElementType type = CorElementType.Max; + + if (clsArgument is RuntimeType) + { + type = RuntimeTypeHandle.GetCorElementType((RuntimeType)clsArgument); + + //GetCorElementType returns CorElementType.Class for both object and string + if (type == CorElementType.Class) + { + if (clsArgument == typeof(object)) + type = CorElementType.Object; + else if (clsArgument == typeof(string)) + type = CorElementType.String; + } + } + + if (IsSimpleType(type)) + { + AddElementType(type); + } + else if (m_module == null) + { + InternalAddRuntimeType(clsArgument); + } + else if (clsArgument.IsValueType) + { + InternalAddTypeToken(m_module.GetTypeToken(clsArgument), CorElementType.ValueType); + } + else + { + InternalAddTypeToken(m_module.GetTypeToken(clsArgument), CorElementType.Class); + } + } + } + + private void AddData(int data) + { + // A managed representation of CorSigCompressData; + + if (m_currSig + 4 > m_signature.Length) + { + m_signature = ExpandArray(m_signature); + } + + if (data <= 0x7F) + { + m_signature[m_currSig++] = (byte)(data & 0xFF); + } + else if (data <= 0x3FFF) + { + m_signature[m_currSig++] = (byte)((data >>8) | 0x80); + m_signature[m_currSig++] = (byte)(data & 0xFF); + } + else if (data <= 0x1FFFFFFF) + { + m_signature[m_currSig++] = (byte)((data >>24) | 0xC0); + m_signature[m_currSig++] = (byte)((data >>16) & 0xFF); + m_signature[m_currSig++] = (byte)((data >>8) & 0xFF); + m_signature[m_currSig++] = (byte)((data) & 0xFF); + } + else + { + throw new ArgumentException(Environment.GetResourceString("Argument_LargeInteger")); + } + + } + + private void AddData(uint data) + { + if (m_currSig + 4 > m_signature.Length) + { + m_signature = ExpandArray(m_signature); + } + + m_signature[m_currSig++] = (byte)((data) & 0xFF); + m_signature[m_currSig++] = (byte)((data>>8) & 0xFF); + m_signature[m_currSig++] = (byte)((data>>16) & 0xFF); + m_signature[m_currSig++] = (byte)((data>>24) & 0xFF); + } + + private void AddData(ulong data) + { + if (m_currSig + 8 > m_signature.Length) + { + m_signature = ExpandArray(m_signature); + } + + m_signature[m_currSig++] = (byte)((data) & 0xFF); + m_signature[m_currSig++] = (byte)((data>>8) & 0xFF); + m_signature[m_currSig++] = (byte)((data>>16) & 0xFF); + m_signature[m_currSig++] = (byte)((data>>24) & 0xFF); + m_signature[m_currSig++] = (byte)((data>>32) & 0xFF); + m_signature[m_currSig++] = (byte)((data>>40) & 0xFF); + m_signature[m_currSig++] = (byte)((data>>48) & 0xFF); + m_signature[m_currSig++] = (byte)((data>>56) & 0xFF); + } + + private void AddElementType(CorElementType cvt) + { + // Adds an element to the signature. A managed represenation of CorSigCompressElement + if (m_currSig + 1 > m_signature.Length) + m_signature = ExpandArray(m_signature); + + m_signature[m_currSig++] = (byte)cvt; + } + + private void AddToken(int token) + { + // A managed represenation of CompressToken + // Pulls the token appart to get a rid, adds some appropriate bits + // to the token and then adds this to the signature. + + int rid = (token & 0x00FFFFFF); //This is RidFromToken; + MetadataTokenType type = (MetadataTokenType)(token & unchecked((int)0xFF000000)); //This is TypeFromToken; + + if (rid > 0x3FFFFFF) + { + // token is too big to be compressed + throw new ArgumentException(Environment.GetResourceString("Argument_LargeInteger")); + } + + rid = (rid << 2); + + // TypeDef is encoded with low bits 00 + // TypeRef is encoded with low bits 01 + // TypeSpec is encoded with low bits 10 + if (type == MetadataTokenType.TypeRef) + { + //if type is mdtTypeRef + rid|=0x1; + } + else if (type == MetadataTokenType.TypeSpec) + { + //if type is mdtTypeSpec + rid|=0x2; + } + + AddData(rid); + } + + private void InternalAddTypeToken(TypeToken clsToken, CorElementType CorType) + { + // Add a type token into signature. CorType will be either CorElementType.Class or CorElementType.ValueType + AddElementType(CorType); + AddToken(clsToken.Token); + } + + [System.Security.SecurityCritical] // auto-generated + private unsafe void InternalAddRuntimeType(Type type) + { + // Add a runtime type into the signature. + + AddElementType(CorElementType.Internal); + + IntPtr handle = type.GetTypeHandleInternal().Value; + + // Internal types must have their pointer written into the signature directly (we don't + // want to convert to little-endian format on big-endian machines because the value is + // going to be extracted and used directly as a pointer (and only within this process)). + + if (m_currSig + sizeof(void*) > m_signature.Length) + m_signature = ExpandArray(m_signature); + + byte *phandle = (byte*)&handle; + for (int i = 0; i < sizeof(void*); i++) + m_signature[m_currSig++] = phandle[i]; + } + + private byte[] ExpandArray(byte[] inArray) + { + // Expand the signature buffer size + return ExpandArray(inArray, inArray.Length * 2); + } + + private byte[] ExpandArray(byte[] inArray, int requiredLength) + { + // Expand the signature buffer size + + if (requiredLength < inArray.Length) + requiredLength = inArray.Length*2; + + byte[] outArray = new byte[requiredLength]; + Array.Copy(inArray, outArray, inArray.Length); + return outArray; + } + + private void IncrementArgCounts() + { + if (m_sizeLoc == NO_SIZE_IN_SIG) + { + //We don't have a size if this is a field. + return; + } + + m_argCount++; + } + + private void SetNumberOfSignatureElements(bool forceCopy) + { + // For most signatures, this will set the number of elements in a byte which we have reserved for it. + // However, if we have a field signature, we don't set the length and return. + // If we have a signature with more than 128 arguments, we can't just set the number of elements, + // we actually have to allocate more space (e.g. shift everything in the array one or more spaces to the + // right. We do this by making a copy of the array and leaving the correct number of blanks. This new + // array is now set to be m_signature and we use the AddData method to set the number of elements properly. + // The forceCopy argument can be used to force SetNumberOfSignatureElements to make a copy of + // the array. This is useful for GetSignature which promises to trim the array to be the correct size anyway. + + byte[] temp; + int newSigSize; + int currSigHolder = m_currSig; + + if (m_sizeLoc == NO_SIZE_IN_SIG) + return; + + //If we have fewer than 128 arguments and we haven't been told to copy the + //array, we can just set the appropriate bit and return. + if (m_argCount < 0x80 && !forceCopy) + { + m_signature[m_sizeLoc] = (byte)m_argCount; + return; + } + + //We need to have more bytes for the size. Figure out how many bytes here. + //Since we need to copy anyway, we're just going to take the cost of doing a + //new allocation. + if (m_argCount < 0x80) + { + newSigSize = 1; + } + else if (m_argCount < 0x4000) + { + newSigSize = 2; + } + else + { + newSigSize = 4; + } + + //Allocate the new array. + temp = new byte[m_currSig + newSigSize - 1]; + + //Copy the calling convention. The calling convention is always just one byte + //so we just copy that byte. Then copy the rest of the array, shifting everything + //to make room for the new number of elements. + temp[0] = m_signature[0]; + Array.Copy(m_signature, m_sizeLoc + 1, temp, m_sizeLoc + newSigSize, currSigHolder - (m_sizeLoc + 1)); + m_signature = temp; + + //Use the AddData method to add the number of elements appropriately compressed. + m_currSig = m_sizeLoc; + AddData(m_argCount); + m_currSig = currSigHolder + (newSigSize - 1); + } + + #endregion + + #region Internal Members + internal int ArgumentCount + { + get + { + return m_argCount; + } + } + + internal static bool IsSimpleType(CorElementType type) + { + if (type <= CorElementType.String) + return true; + + if (type == CorElementType.TypedByRef || type == CorElementType.I || type == CorElementType.U || type == CorElementType.Object) + return true; + + return false; + } + + internal byte[] InternalGetSignature(out int length) + { + // An internal method to return the signature. Does not trim the + // array, but passes out the length of the array in an out parameter. + // This is the actual array -- not a copy -- so the callee must agree + // to not copy it. + // + // param length : an out param indicating the length of the array. + // return : A reference to the internal ubyte array. + + if (!m_sigDone) + { + m_sigDone = true; + + // If we have more than 128 variables, we can't just set the length, we need + // to compress it. Unfortunately, this means that we need to copy the entire + // array. Bummer, eh? + SetNumberOfSignatureElements(false); + } + + length = m_currSig; + return m_signature; + } + + + + + internal byte[] InternalGetSignatureArray() + { + int argCount = m_argCount; + int currSigLength = m_currSig; + int newSigSize = currSigLength; + + //Allocate the new array. + if (argCount < 0x7F) + newSigSize += 1; + else if (argCount < 0x3FFF) + newSigSize += 2; + else + newSigSize += 4; + byte[] temp = new byte[newSigSize]; + + // copy the sig + int sigCopyIndex = 0; + // calling convention + temp[sigCopyIndex++] = m_signature[0]; + // arg size + if (argCount <= 0x7F) + temp[sigCopyIndex++] = (byte)(argCount & 0xFF); + else if (argCount <= 0x3FFF) + { + temp[sigCopyIndex++] = (byte)((argCount >>8) | 0x80); + temp[sigCopyIndex++] = (byte)(argCount & 0xFF); + } + else if (argCount <= 0x1FFFFFFF) + { + temp[sigCopyIndex++] = (byte)((argCount >>24) | 0xC0); + temp[sigCopyIndex++] = (byte)((argCount >>16) & 0xFF); + temp[sigCopyIndex++] = (byte)((argCount >>8) & 0xFF); + temp[sigCopyIndex++] = (byte)((argCount) & 0xFF); + } + else + throw new ArgumentException(Environment.GetResourceString("Argument_LargeInteger")); + // copy the sig part of the sig + Array.Copy(m_signature, 2, temp, sigCopyIndex, currSigLength - 2); + // mark the end of sig + temp[newSigSize - 1] = (byte)CorElementType.End; + + return temp; + } + + #endregion + + #region Public Methods + public void AddArgument(Type clsArgument) + { + AddArgument(clsArgument, null, null); + } + + [System.Security.SecuritySafeCritical] // auto-generated + public void AddArgument(Type argument, bool pinned) + { + if (argument == null) + throw new ArgumentNullException("argument"); + + IncrementArgCounts(); + AddOneArgTypeHelper(argument, pinned); + } + + public void AddArguments(Type[] arguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers) + { + if (requiredCustomModifiers != null && (arguments == null || requiredCustomModifiers.Length != arguments.Length)) + throw new ArgumentException(Environment.GetResourceString("Argument_MismatchedArrays", "requiredCustomModifiers", "arguments")); + + if (optionalCustomModifiers != null && (arguments == null || optionalCustomModifiers.Length != arguments.Length)) + throw new ArgumentException(Environment.GetResourceString("Argument_MismatchedArrays", "optionalCustomModifiers", "arguments")); + + if (arguments != null) + { + for (int i =0; i < arguments.Length; i++) + { + AddArgument(arguments[i], + requiredCustomModifiers == null ? null : requiredCustomModifiers[i], + optionalCustomModifiers == null ? null : optionalCustomModifiers[i]); + } + } + } + + [System.Security.SecuritySafeCritical] // auto-generated + public void AddArgument(Type argument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers) + { + if (m_sigDone) + throw new ArgumentException(Environment.GetResourceString("Argument_SigIsFinalized")); + + if (argument == null) + throw new ArgumentNullException("argument"); + + IncrementArgCounts(); + + // Add an argument to the signature. Takes a Type and determines whether it + // is one of the primitive types of which we have special knowledge or a more + // general class. In the former case, we only add the appropriate short cut encoding, + // otherwise we will calculate proper description for the type. + AddOneArgTypeHelper(argument, requiredCustomModifiers, optionalCustomModifiers); + } + + public void AddSentinel() + { + AddElementType(CorElementType.Sentinel); + } + + public override bool Equals(Object obj) + { + if (!(obj is SignatureHelper)) + { + return false; + } + + SignatureHelper temp = (SignatureHelper)obj; + + if ( !temp.m_module.Equals(m_module) || temp.m_currSig!=m_currSig || temp.m_sizeLoc!=m_sizeLoc || temp.m_sigDone !=m_sigDone ) + { + return false; + } + + for (int i=0; i<m_currSig; i++) + { + if (m_signature[i]!=temp.m_signature[i]) + return false; + } + return true; + } + + public override int GetHashCode() + { + // Start the hash code with the hash code of the module and the values of the member variables. + int HashCode = m_module.GetHashCode() + m_currSig + m_sizeLoc; + + // Add one if the sig is done. + if (m_sigDone) + HashCode += 1; + + // Then add the hash code of all the arguments. + for (int i=0; i < m_currSig; i++) + HashCode += m_signature[i].GetHashCode(); + + return HashCode; + } + + public byte[] GetSignature() + { + return GetSignature(false); + } + + internal byte[] GetSignature(bool appendEndOfSig) + { + // Chops the internal signature to the appropriate length. Adds the + // end token to the signature and marks the signature as finished so that + // no further tokens can be added. Return the full signature in a trimmed array. + if (!m_sigDone) + { + if (appendEndOfSig) + AddElementType(CorElementType.End); + SetNumberOfSignatureElements(true); + m_sigDone = true; + } + + // This case will only happen if the user got the signature through + // InternalGetSignature first and then called GetSignature. + if (m_signature.Length > m_currSig) + { + byte[] temp = new byte[m_currSig]; + Array.Copy(m_signature, temp, m_currSig); + m_signature = temp; + } + + return m_signature; + } + + public override String ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("Length: " + m_currSig + Environment.NewLine); + + if (m_sizeLoc != -1) + { + sb.Append("Arguments: " + m_signature[m_sizeLoc] + Environment.NewLine); + } + else + { + sb.Append("Field Signature" + Environment.NewLine); + } + + sb.Append("Signature: " + Environment.NewLine); + for (int i=0; i<=m_currSig; i++) + { + sb.Append(m_signature[i] + " "); + } + + sb.Append(Environment.NewLine); + return sb.ToString(); + } + + #endregion + +#if !FEATURE_CORECLR + void _SignatureHelper.GetTypeInfoCount(out uint pcTInfo) + { + throw new NotImplementedException(); + } + + void _SignatureHelper.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) + { + throw new NotImplementedException(); + } + + void _SignatureHelper.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) + { + throw new NotImplementedException(); + } + + void _SignatureHelper.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) + { + throw new NotImplementedException(); + } +#endif + + } +} + + + + + + + + + + + + + + + + + + + + + + + + + |