Skip to content

Commit

Permalink
[corlib] Bring AssemblyName(string) to the happy C# world.
Browse files Browse the repository at this point in the history
  • Loading branch information
kumpera authored and lambdageek committed Jul 29, 2016
1 parent 277aab6 commit ff86e02
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 67 deletions.
9 changes: 9 additions & 0 deletions mcs/class/corlib/Mono/RuntimeMarshal.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

namespace Mono {
internal static class RuntimeMarshal {
Expand All @@ -10,6 +11,11 @@ internal static string PtrToUtf8String (IntPtr ptr)
}
}

internal static SafeStringMarshal MarshalString (string str)
{
return new SafeStringMarshal (str);
}

static int DecodeBlobSize (IntPtr in_ptr, out IntPtr out_ptr)
{
uint size;
Expand Down Expand Up @@ -52,5 +58,8 @@ internal static int AsciHexDigitValue (int c)
return c - 'a' + 10;
return c - 'A' + 10;
}

[MethodImpl (MethodImplOptions.InternalCall)]
internal static extern void FreeAssemblyName (ref MonoAssemblyName name);
}
}
96 changes: 56 additions & 40 deletions mcs/class/corlib/System.Reflection/AssemblyName.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,29 @@ public AssemblyName ()
}

[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")]
Expand Down Expand Up @@ -454,53 +466,57 @@ public AssemblyContentType ContentType {
[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;
}
Expand Down
1 change: 1 addition & 0 deletions mono/metadata/assembly.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion mono/metadata/icall-def.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
35 changes: 9 additions & 26 deletions mono/metadata/icall.c
Original file line number Diff line number Diff line change
Expand Up @@ -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*
Expand Down

0 comments on commit ff86e02

Please sign in to comment.