//
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//
// System.Reflection.Emit/SignatureHelper.cs
//
// Author:
// Paolo Molaro (lupus@ximian.com)
//
// (C) 2001 Ximian, Inc. http://www.ximian.com
//
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace System.Reflection.Emit{
[ComVisible (true)]
[ComDefaultInterface (typeof (_SignatureHelper))]
[ClassInterface (ClassInterfaceType.None)]
public sealed class SignatureHelper : _SignatureHelper {
internal enum SignatureHelperType {
HELPER_FIELD,
HELPER_LOCAL,
HELPER_METHOD,
HELPER_PROPERTY
}
private ModuleBuilder module; // can be null in 2.0
private Type[] arguments;
private SignatureHelperType type;
private Type returnType;
private CallingConventions callConv;
private CallingConvention unmanagedCallConv;
#pragma warning disable 649
private Type[][] modreqs;
private Type[][] modopts;
#pragma warning restore 649
internal SignatureHelper (ModuleBuilder module, SignatureHelperType type)
{
this.type = type;
this.module = module;
}
public static SignatureHelper GetFieldSigHelper (Module mod)
{
if (mod != null && !(mod is ModuleBuilder))
throw new ArgumentException ("ModuleBuilder is expected");
return new SignatureHelper ((ModuleBuilder) mod, SignatureHelperType.HELPER_FIELD);
}
public static SignatureHelper GetLocalVarSigHelper (Module mod)
{
if (mod != null && !(mod is ModuleBuilder))
throw new ArgumentException ("ModuleBuilder is expected");
return new SignatureHelper ((ModuleBuilder) mod, SignatureHelperType.HELPER_LOCAL);
}
public static SignatureHelper GetLocalVarSigHelper ()
{
return new SignatureHelper (null, SignatureHelperType.HELPER_LOCAL);
}
public static SignatureHelper GetMethodSigHelper (CallingConventions callingConvention, Type returnType)
{
return GetMethodSigHelper (null, callingConvention, (CallingConvention)0, returnType, null);
}
public static SignatureHelper GetMethodSigHelper (CallingConvention unmanagedCallingConvention, Type returnType)
{
return GetMethodSigHelper (null, CallingConventions.Standard, unmanagedCallingConvention, returnType, null);
}
public static SignatureHelper GetMethodSigHelper (Module mod, CallingConventions callingConvention, Type returnType)
{
return GetMethodSigHelper (mod, callingConvention, (CallingConvention)0, returnType, null);
}
public static SignatureHelper GetMethodSigHelper (Module mod, CallingConvention unmanagedCallConv, Type returnType)
{
return GetMethodSigHelper (mod, CallingConventions.Standard, unmanagedCallConv, returnType, null);
}
public static SignatureHelper GetMethodSigHelper (Module mod, Type returnType, Type[] parameterTypes)
{
return GetMethodSigHelper (mod, CallingConventions.Standard, (CallingConvention)0, returnType, parameterTypes);
}
[MonoTODO("Not implemented")]
public static SignatureHelper GetPropertySigHelper (Module mod, Type returnType, Type[] parameterTypes)
{
throw new NotImplementedException ();
}
//
// Grows the given array, and returns the index where the element
// was added
//
static int AppendArray (ref Type [] array, Type t)
{
if (array != null) {
Type[] new_a = new Type [array.Length + 1];
System.Array.Copy (array, new_a, array.Length);
new_a [array.Length] = t;
array = new_a;
return array.Length-1;
} else {
array = new Type [1];
array [0] = t;
return 0;
}
}
//
// Appends the given type array @t into the @array passed at
// position @pos. If there is no array, it gets created
//
// This allows adding data to a null array at position 5 for
// example, creating 4 empty slots before the slot where @t
// is stored.
//
//
static void AppendArrayAt (ref Type [][] array, Type [] t, int pos)
{
int top = Math.Max (pos, array == null ? 0 : array.Length);
Type[][] new_a = new Type [top+1][];
if (array != null)
System.Array.Copy (array, new_a, top);
new_a [pos] = t;
array = new_a;
}
static void ValidateParameterModifiers (string name, Type [] parameter_modifiers)
{
foreach (Type modifier in parameter_modifiers){
if (modifier == null)
throw new ArgumentNullException (name);
if (modifier.IsArray)
throw new ArgumentException (Locale.GetText ("Array type not permitted"), name);
if (modifier.ContainsGenericParameters)
throw new ArgumentException (Locale.GetText ("Open Generic Type not permitted"), name);
}
}
static void ValidateCustomModifier (int n, Type [][] custom_modifiers, string name)
{
if (custom_modifiers == null)
return;
if (custom_modifiers.Length != n)
throw new ArgumentException (
Locale.GetText (
String.Format ("Custom modifiers length `{0}' does not match the size of the arguments")));
foreach (Type [] parameter_modifiers in custom_modifiers){
if (parameter_modifiers == null)
continue;
ValidateParameterModifiers (name, parameter_modifiers);
}
}
static Exception MissingFeature ()
{
throw new NotImplementedException ("Mono does not currently support setting modOpt/modReq through SignatureHelper");
}
[MonoTODO("Currently we ignore requiredCustomModifiers and optionalCustomModifiers")]
public void AddArguments (Type[] arguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
{
if (arguments == null)
throw new ArgumentNullException ("arguments");
// For now
if (requiredCustomModifiers != null || optionalCustomModifiers != null){
throw MissingFeature();
}
ValidateCustomModifier (arguments.Length, requiredCustomModifiers, "requiredCustomModifiers");
ValidateCustomModifier (arguments.Length, optionalCustomModifiers, "optionalCustomModifiers");
for (int i = 0; i < arguments.Length; i++){
AddArgument (arguments [i],
requiredCustomModifiers != null ? requiredCustomModifiers [i] : null,
optionalCustomModifiers != null ? optionalCustomModifiers [i] : null);
}
}
[MonoTODO ("pinned is ignored")]
public void AddArgument (Type argument, bool pinned)
{
AddArgument (argument);
}
public void AddArgument (Type argument, Type [] requiredCustomModifiers, Type [] optionalCustomModifiers)
{
if (argument == null)
throw new ArgumentNullException ("argument");
if (requiredCustomModifiers != null)
ValidateParameterModifiers ("requiredCustomModifiers", requiredCustomModifiers);
if (optionalCustomModifiers != null)
ValidateParameterModifiers ("optionalCustomModifiers", optionalCustomModifiers);
int p = AppendArray (ref arguments, argument);
if (requiredCustomModifiers != null)
AppendArrayAt (ref modreqs, requiredCustomModifiers, p);
if (optionalCustomModifiers != null)
AppendArrayAt (ref modopts, optionalCustomModifiers, p);
}
[MonoTODO("Not implemented")]
public static SignatureHelper GetPropertySigHelper (Module mod, Type returnType,
Type [] requiredReturnTypeCustomModifiers,
Type [] optionalReturnTypeCustomModifiers,
Type [] parameterTypes,
Type [] [] requiredParameterTypeCustomModifiers,
Type [] [] optionalParameterTypeCustomModifiers)
{
throw new NotImplementedException ();
}
public void AddArgument (Type clsArgument)
{
if (clsArgument == null)
throw new ArgumentNullException ("clsArgument");
AppendArray (ref arguments, clsArgument);
}
[MonoTODO("Not implemented")]
public void AddSentinel ()
{
throw new NotImplementedException ();
}
static bool CompareOK (Type [][] one, Type [][] two)
{
if (one == null){
if (two == null)
return true;
return false;
} else if (two == null)
return false;
if (one.Length != two.Length)
return false;
for (int i = 0; i < one.Length; i++){
Type [] tone = one [i];
Type [] ttwo = two [i];
if (tone == null){
if (ttwo == null)
continue;
} else if (ttwo == null)
return false;
if (tone.Length != ttwo.Length)
return false;
for (int j = 0; j < tone.Length; j++){
Type uone = tone [j];
Type utwo = ttwo [j];
if (uone == null){
if (utwo == null)
continue;
return false;
} else if (utwo == null)
return false;
if (!uone.Equals (utwo))
return false;
}
}
return true;
}
public override bool Equals (object obj)
{
SignatureHelper other = obj as SignatureHelper;
if (other == null)
return false;
if (other.module != module ||
other.returnType != returnType ||
other.callConv != callConv ||
other.unmanagedCallConv != unmanagedCallConv)
return false;
if (arguments != null){
if (other.arguments == null)
return false;
if (arguments.Length != other.arguments.Length)
return false;
for (int i = 0; i < arguments.Length; i++)
if (!other.arguments [i].Equals (arguments [i]))
return false;
} else if (other.arguments != null)
return false;
return CompareOK (other.modreqs, modreqs) && CompareOK (other.modopts, modopts);
}
public override int GetHashCode ()
{
// Lame, but easy, and will work, and chances are
// you will only need a few of these.
return 0;
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal extern byte[] get_signature_local ();
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal extern byte[] get_signature_field ();
public byte[] GetSignature ()
{
switch (type) {
case SignatureHelperType.HELPER_LOCAL:
return get_signature_local ();
case SignatureHelperType.HELPER_FIELD:
return get_signature_field ();
default:
throw new NotImplementedException ();
}
}
public override string ToString() {
return "SignatureHelper";
}
internal static SignatureHelper GetMethodSigHelper (Module mod, CallingConventions callingConvention, CallingConvention unmanagedCallingConvention, Type returnType,
Type [] parameters)
{
if (mod != null && !(mod is ModuleBuilder))
throw new ArgumentException ("ModuleBuilder is expected");
if (returnType == null)
returnType = typeof (void);
if (returnType.IsUserType)
throw new NotSupportedException ("User defined subclasses of System.Type are not yet supported.");
if (parameters != null) {
for (int i = 0; i < parameters.Length; ++i)
if (parameters [i].IsUserType)
throw new NotSupportedException ("User defined subclasses of System.Type are not yet supported.");
}
SignatureHelper helper =
new SignatureHelper ((ModuleBuilder)mod, SignatureHelperType.HELPER_METHOD);
helper.returnType = returnType;
helper.callConv = callingConvention;
helper.unmanagedCallConv = unmanagedCallingConvention;
if (parameters != null) {
helper.arguments = new Type [parameters.Length];
for (int i = 0; i < parameters.Length; ++i)
helper.arguments [i] = parameters [i];
}
return helper;
}
void _SignatureHelper.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
{
throw new NotImplementedException ();
}
void _SignatureHelper.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
{
throw new NotImplementedException ();
}
void _SignatureHelper.GetTypeInfoCount (out uint pcTInfo)
{
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 ();
}
}
}
|