[corlib] Bring AssemblyName(string) to the happy C# world.
authorRodrigo Kumpera <kumpera@gmail.com>
Fri, 10 Jun 2016 23:38:40 +0000 (16:38 -0700)
committerAleksey Kliger <aleksey@xamarin.com>
Fri, 29 Jul 2016 20:18:15 +0000 (16:18 -0400)
mcs/class/corlib/Mono/RuntimeMarshal.cs
mcs/class/corlib/System.Reflection/AssemblyName.cs
mono/metadata/assembly.c
mono/metadata/icall-def.h
mono/metadata/icall.c

index 6e3ed1daddfde735a2b9665e312b9b4624355406..38da4e2201afee31704d18e3d34c9a23cf7442f7 100644 (file)
@@ -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);
        }
 }
index 4ec94fe3e1a9013f60a2ad15908b4efdb99cff0a..7ce7241cc98c8851f6893ca193722e3c679c5f90 100644 (file)
@@ -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<byte>.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<byte>.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<byte>.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<byte>.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;
                }
index d59d688c9aef2e19d3488905b241e225f2fdb8a1..4bad7dc5ed6d85719bd7426b3e906655c833c127 100644 (file)
@@ -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
index 392d9e98a57cfc04226b2d09b42be57f90acc4f6..d529af28d6c79fc479268620d7795659c05b27d8 100644 (file)
@@ -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)
index 02f53da45626a444dde2669675e32db55d9c1d85..2e3240354898d39ce5f3facc3d931fe501e45420 100644 (file)
@@ -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*