From ff86e021c06a8eae2a0800008a61fc6b8da2920a Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Fri, 10 Jun 2016 16:38:40 -0700 Subject: [PATCH] [corlib] Bring AssemblyName(string) to the happy C# world. --- mcs/class/corlib/Mono/RuntimeMarshal.cs | 9 ++ .../corlib/System.Reflection/AssemblyName.cs | 96 +++++++++++-------- mono/metadata/assembly.c | 1 + mono/metadata/icall-def.h | 5 +- mono/metadata/icall.c | 35 ++----- 5 files changed, 79 insertions(+), 67 deletions(-) diff --git a/mcs/class/corlib/Mono/RuntimeMarshal.cs b/mcs/class/corlib/Mono/RuntimeMarshal.cs index 6e3ed1daddf..38da4e2201a 100644 --- a/mcs/class/corlib/Mono/RuntimeMarshal.cs +++ b/mcs/class/corlib/Mono/RuntimeMarshal.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; namespace Mono { internal static class RuntimeMarshal { @@ -10,6 +11,11 @@ namespace Mono { } } + internal static SafeStringMarshal MarshalString (string str) + { + return new SafeStringMarshal (str); + } + static int DecodeBlobSize (IntPtr in_ptr, out IntPtr out_ptr) { uint size; @@ -52,5 +58,8 @@ namespace Mono { return c - 'a' + 10; return c - 'A' + 10; } + + [MethodImpl (MethodImplOptions.InternalCall)] + internal static extern void FreeAssemblyName (ref MonoAssemblyName name); } } diff --git a/mcs/class/corlib/System.Reflection/AssemblyName.cs b/mcs/class/corlib/System.Reflection/AssemblyName.cs index 4ec94fe3e1a..7ce7241cc98 100644 --- a/mcs/class/corlib/System.Reflection/AssemblyName.cs +++ b/mcs/class/corlib/System.Reflection/AssemblyName.cs @@ -85,17 +85,29 @@ namespace System.Reflection { } [MethodImpl (MethodImplOptions.InternalCall)] - static extern bool ParseName (AssemblyName aname, string assemblyName); - + static extern bool ParseAssemblyName (IntPtr name, out MonoAssemblyName aname, out bool is_version_definited, out bool is_token_defined); + public AssemblyName (string assemblyName) { if (assemblyName == null) throw new ArgumentNullException ("assemblyName"); if (assemblyName.Length < 1) throw new ArgumentException ("assemblyName cannot have zero length."); - - if (!ParseName (this, assemblyName)) - throw new FileLoadException ("The assembly name is invalid."); + + using (var name = RuntimeMarshal.MarshalString (assemblyName)) { + MonoAssemblyName nativeName; + bool isVersionDefined, isTokenDefined; + //ParseName free the name if it fails. + if (!ParseAssemblyName (name.Value, out nativeName, out isVersionDefined, out isTokenDefined)) + throw new FileLoadException ("The assembly name is invalid."); + try { + unsafe { + this.FillName (&nativeName, null, isVersionDefined, false, isTokenDefined); + } + } finally { + RuntimeMarshal.FreeAssemblyName (ref nativeName); + } + } } [MonoLimitation ("Not used, as the values are too limited; Mono supports more")] @@ -454,53 +466,57 @@ namespace System.Reflection { [MethodImplAttribute (MethodImplOptions.InternalCall)] static extern unsafe MonoAssemblyName* GetNativeName (IntPtr assembly_ptr); - internal static AssemblyName Create (Assembly assembly, bool fillCodebase) + internal unsafe void FillName (MonoAssemblyName *native, string codeBase, bool addVersion, bool addPublickey, bool defaultToken) { - AssemblyName aname = new AssemblyName (); - unsafe { - MonoAssemblyName *native = GetNativeName (assembly._mono_assembly); + this.name = RuntimeMarshal.PtrToUtf8String (native->name); - aname.name = RuntimeMarshal.PtrToUtf8String (native->name); + this.major = native->major; + this.minor = native->minor; + this.build = native->build; + this.revision = native->revision; - aname.major = native->major; - aname.minor = native->minor; - aname.build = native->build; - aname.revision = native->revision; + this.flags = (AssemblyNameFlags)native->flags; - aname.flags = (AssemblyNameFlags)native->flags; + this.hashalg = (AssemblyHashAlgorithm)native->hash_alg; - aname.hashalg = (AssemblyHashAlgorithm)native->hash_alg; + this.versioncompat = AssemblyVersionCompatibility.SameMachine; + this.processor_architecture = (ProcessorArchitecture)native->arch; - aname.versioncompat = AssemblyVersionCompatibility.SameMachine; - aname.processor_architecture = (ProcessorArchitecture)native->arch; + if (addVersion) + this.version = new Version (this.major, this.minor, this.build, this.revision); - aname.version = new Version (aname.major, aname.minor, aname.build, aname.revision); + this.codebase = codeBase; - if (fillCodebase) - aname.codebase = assembly.CodeBase; + if (native->culture != IntPtr.Zero) + this.cultureinfo = CultureInfo.CreateCulture ( RuntimeMarshal.PtrToUtf8String (native->culture), false); - if (native->culture != IntPtr.Zero) - aname.cultureinfo = CultureInfo.CreateCulture ( RuntimeMarshal.PtrToUtf8String (native->culture), false); + if (native->public_key != IntPtr.Zero) { + this.publicKey = RuntimeMarshal.DecodeBlobArray (native->public_key); + this.flags |= AssemblyNameFlags.PublicKey; + } else if (addPublickey) { + this.publicKey = EmptyArray.Value; + this.flags |= AssemblyNameFlags.PublicKey; + } - if (native->public_key != IntPtr.Zero) { - aname.publicKey = RuntimeMarshal.DecodeBlobArray (native->public_key); - aname.flags |= AssemblyNameFlags.PublicKey; - } else { - aname.publicKey = EmptyArray.Value; - aname.flags |= AssemblyNameFlags.PublicKey; + // MonoAssemblyName keeps the public key token as an hexadecimal string + if (native->public_key_token [0] != 0) { + byte[] keyToken = new byte [8]; + for (int i = 0, j = 0; i < 8; ++i) { + keyToken [i] = (byte)(RuntimeMarshal.AsciHexDigitValue (native->public_key_token [j++]) << 4); + keyToken [i] |= (byte)RuntimeMarshal.AsciHexDigitValue (native->public_key_token [j++]); } + this.keyToken = keyToken; + } else if (defaultToken) { + this.keyToken = EmptyArray.Value; + } + } - // MonoAssemblyName keeps the public key token as an hexadecimal string - if (native->public_key_token [0] != 0) { - byte[] keyToken = new byte [8]; - for (int i = 0, j = 0; i < 8; ++i) { - keyToken [i] = (byte)(RuntimeMarshal.AsciHexDigitValue (native->public_key_token [j++]) << 4); - keyToken [i] |= (byte)RuntimeMarshal.AsciHexDigitValue (native->public_key_token [j++]); - } - aname.keyToken = keyToken; - } else { - aname.keyToken = EmptyArray.Value; - } + internal static AssemblyName Create (Assembly assembly, bool fillCodebase) + { + AssemblyName aname = new AssemblyName (); + unsafe { + MonoAssemblyName *native = GetNativeName (assembly._mono_assembly); + aname.FillName (native, fillCodebase ? assembly.CodeBase : null, true, true, true); } return aname; } diff --git a/mono/metadata/assembly.c b/mono/metadata/assembly.c index d59d688c9ae..4bad7dc5ed6 100644 --- a/mono/metadata/assembly.c +++ b/mono/metadata/assembly.c @@ -1999,6 +1999,7 @@ mono_assembly_name_free (MonoAssemblyName *aname) g_free ((void *) aname->name); g_free ((void *) aname->culture); g_free ((void *) aname->hash_value); + g_free ((guint8*) aname->public_key); } static gboolean diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index 392d9e98a57..d529af28d6c 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -68,6 +68,9 @@ ICALL(RTCLASS_1, "GetTypeFromClass", ves_icall_Mono_RuntimeClassHandle_GetTypeFr ICALL_TYPE(RTPTRARRAY, "Mono.RuntimeGPtrArrayHandle", RTPTRARRAY_1) ICALL(RTPTRARRAY_1, "GPtrArrayFree", ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree) +ICALL_TYPE(RTMARSHAL, "Mono.RuntimeMarshal", RTMARSHAL_1) +ICALL(RTMARSHAL_1, "FreeAssemblyName", ves_icall_Mono_RuntimeMarshal_FreeAssemblyName) + ICALL_TYPE(SAFESTRMARSHAL, "Mono.SafeStringMarshal", SAFESTRMARSHAL_1) ICALL(SAFESTRMARSHAL_1, "GFree", ves_icall_Mono_SafeStringMarshal_GFree) ICALL(SAFESTRMARSHAL_2, "StringToUtf8", ves_icall_Mono_SafeStringMarshal_StringToUtf8) @@ -495,7 +498,7 @@ ICALL(ASSEM_26, "load_with_partial_name", ves_icall_System_Reflection_Assembly_l ICALL_TYPE(ASSEMN, "System.Reflection.AssemblyName", ASSEMN_0) ICALL(ASSEMN_0, "GetNativeName", ves_icall_System_Reflection_AssemblyName_GetNativeName) -ICALL(ASSEMN_1, "ParseName", ves_icall_System_Reflection_AssemblyName_ParseName) +ICALL(ASSEMN_3, "ParseAssemblyName", ves_icall_System_Reflection_AssemblyName_ParseAssemblyName) ICALL(ASSEMN_2, "get_public_token", mono_digest_get_public_token) ICALL_TYPE(CATTR_DATA, "System.Reflection.CustomAttributeData", CATTR_DATA_1) diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index 02f53da4562..2e324035489 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -5756,35 +5756,18 @@ ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, return res; } -ICALL_EXPORT gboolean -ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname) +ICALL_EXPORT void +ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname) { - MonoError error; - MonoAssemblyName aname; - MonoDomain *domain = mono_object_domain (name); - char *val; - gboolean is_version_defined; - gboolean is_token_defined; - - aname.public_key = NULL; - val = mono_string_to_utf8_checked (assname, &error); - if (mono_error_set_pending_exception (&error)) - return FALSE; - - if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) { - g_free ((guint8*) aname.public_key); - g_free (val); - return FALSE; - } - - fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error); - mono_error_set_pending_exception (&error); + mono_assembly_name_free (aname); +} - mono_assembly_name_free (&aname); - g_free ((guint8*) aname.public_key); - g_free (val); +ICALL_EXPORT gboolean +ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined) +{ + *is_version_definited = *is_token_defined = FALSE; - return TRUE; + return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined); } ICALL_EXPORT MonoReflectionType* -- 2.25.1