Re: [Mono-dev] [Patch] AssemblyName ctor (with corrections)
Hey Paolo, Thanks for the comments. Carlos. El mié, 14-09-2005 a las 20:45 +0200, Paolo Molaro escribió: On 09/01/05 Carlos Alberto Cortez wrote: Index: AssemblyName.cs === --- AssemblyName.cs (revisión: 48811) +++ AssemblyName.cs (copia de trabajo) @@ -37,6 +37,7 @@ using System.Text; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; +using System.IO; using Mono.Security; @@ -80,12 +81,23 @@ versioncompat = AssemblyVersionCompatibility.SameMachine; } -#if NET_2_0 +#if NET_2_0 || BOOTSTRAP_NET_2_0 + [MethodImpl (MethodImplOptions.InternalCall)] + static extern bool ParseName (AssemblyName aname, string assemblyName); + public AssemblyName (string assemblyName) { - name = 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.); Is a FileLoadException really ok? Do you have tests for this? Index: assembly.c === --- assembly.c (revisión: 48811) +++ assembly.c (copia de trabajo) @@ -1171,10 +1171,92 @@ g_free ((void *) aname-hash_value); } +static gint +to_int32_le (gchar bytes [], gint offset) +{ + return (bytes [offset+3] 24) | (bytes [offset+2] 16) | (bytes [offset+1] 8) | bytes [offset]; +} + The function name looks wrong. You should likely use read32() anyway. static gboolean -build_assembly_name (const char *name, const char *version, const char *culture, const char *token, MonoAssemblyName *aname) +parse_public_key (const gchar *key, const gchar** pubkey) { [...] + if (key strncmp (key, null, 4) != 0) { + if (!parse_public_key (key, (const gchar**) pkey)) { Why declare parse_public_key() to take a const gchar** when it's not in the only place it's called? + + if (!g_ascii_strncasecmp (value, PublicKey=, 10)) { + key = g_strstrip (value + 10); Where is key freed? + tmp++; + continue; + } g_strfreev (parts); return FALSE; } - res = build_assembly_name (dllname, version, culture, token, aname); + res = build_assembly_name (dllname, version, culture, token, key, aname, save_public_key); g_strfreev (parts); return res; } [...] Index: icall.c === --- icall.c (revisión: 48811) +++ icall.c (copia de trabajo) @@ -4152,9 +4152,11 @@ mono_method_desc_free (desc); } - args [0] = mono_string_new (domain, name-culture); - aname-cultureInfo = - mono_runtime_invoke (create_culture, NULL, args, NULL); + if (name-culture) { + args [0] = mono_string_new (domain, name-culture); + aname-cultureInfo = + mono_runtime_invoke (create_culture, NULL, args, NULL); Put on the same line. Thanks. Once you'll have fixed the remaining issues, please commit. lupus ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list
Re: [Mono-dev] [Patch] AssemblyName ctor (yes, again)
On 08/24/05 Carlos Alberto Cortez wrote: The attached patches contain some changes to runtime functions to support the new AssemblyName ctor. They also add an internal call for this ctor. I added a pair of new fields to MonoAssemblyName (is_persistent and is_version_defined) to define if the public_key was parsed (should be freed) or is persistent (image metadata). The second is used for avoiding creating the version if it was not defined (I need it to mimic .Net behavior). Comments? PD - The run rests fine with the patches. Index: assembly.c === --- assembly.c(revisión: 48811) +++ assembly.c(copia de trabajo) @@ -449,6 +449,7 @@ mono_metadata_decode_row (t, 0, cols, MONO_ASSEMBLY_SIZE); + aname-is_persistent = TRUE; aname-hash_len = 0; aname-hash_value = NULL; aname-name = mono_metadata_string_heap (image, cols [MONO_ASSEMBLY_NAME]); @@ -458,6 +459,7 @@ aname-minor = cols [MONO_ASSEMBLY_MINOR_VERSION]; aname-build = cols [MONO_ASSEMBLY_BUILD_NUMBER]; aname-revision = cols [MONO_ASSEMBLY_REV_NUMBER]; + aname-is_version_defined = TRUE; aname-hash_alg = cols [MONO_ASSEMBLY_HASH_ALG]; if (cols [MONO_ASSEMBLY_PUBLIC_KEY]) { gchar* token = g_malloc (8); @@ -1169,23 +1171,35 @@ g_free ((void *) aname-name); g_free ((void *) aname-culture); g_free ((void *) aname-hash_value); + + if (!aname-is_persistent) + g_free ((void *) aname-public_key); } static gboolean -build_assembly_name (const char *name, const char *version, const char *culture, const char *token, MonoAssemblyName *aname) +build_assembly_name (const char *name, const char *version, const char *culture, const char *token, const char *key, MonoAssemblyName *aname) { gint major, minor, build, revision; memset (aname, 0, sizeof (MonoAssemblyName)); if (version) { - if (sscanf (version, %u.%u.%u.%u, major, minor, build, revision) != 4) + gchar **tmp, **parts = g_strsplit (version, ., 4); + + tmp = parts; + major = *tmp ? atoi (*tmp++) : -1; Use strtol() for proper error checking. + aname-major = (guint16) major; Why the cast? @@ -1197,8 +1211,35 @@ aname-culture = g_strdup (culture); } - if (token strncmp (token, null, 4) != 0) + if (token strncmp (token, null, 4) != 0) { + if (strlen (token) != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) + return FALSE; + g_strlcpy ((char*)aname-public_key_token, token, MONO_PUBLIC_KEY_TOKEN_LENGTH); + } + + if (key strncmp (key, null, 4) != 0) { + gchar *arr, *tok, *encoded; + int i, j; + + if (strlen (key) != MONO_PUBLIC_KEY_LENGTH) + return FALSE; Can't the length change based on the flags? Sebastien? + arr = g_malloc (160); + for (i = 0, j = 0; i 160; i++) { + arr [i] = g_ascii_xdigit_value (key [j++]) 4; + arr [i] |= g_ascii_xdigit_value (key [j++]); + } + aname-public_key = (guint8*) arr; + + // We also need to generate the key token + tok = g_malloc (8); Ugh, just alloc it on the stack. + mono_digest_get_public_token ((guchar*) tok, aname-public_key, 160); + encoded = encode_public_tok ((guchar*) tok, 8); + g_strlcpy ((char*)aname-public_key_token, encoded, MONO_PUBLIC_KEY_TOKEN_LENGTH); + g_free (tok); + g_free (encoded); + } return TRUE; } @@ -1215,7 +1256,7 @@ return FALSE; } - res = build_assembly_name (name, parts[0], parts[1], parts[2], aname); + res = build_assembly_name (name, parts[0], parts[1], parts[2], NULL, aname); g_strfreev (parts); return res; } @@ -1236,6 +1277,7 @@ gchar *version = NULL; gchar *culture = NULL; gchar *token = NULL; + gchar *key = NULL; gboolean res; gchar *value; gchar **parts; @@ -1270,12 +1312,18 @@ tmp++; continue; } + + if (!g_ascii_strncasecmp (value, PublicKey=, 10)) { + key = g_strstrip (value + 10); + tmp++; + continue; + } g_strfreev (parts); return FALSE; } - res = build_assembly_name (dllname, version, culture, token, aname); + res = build_assembly_name (dllname, version, culture, token, key, aname); g_strfreev (parts); return res; } Index: image.h
Re: [Mono-dev] [Patch] AssemblyName ctor (yes, again)
On Thu, 2005-25-08 at 15:42 +0200, Paolo Molaro wrote: @@ -1197,8 +1211,35 @@ aname-culture = g_strdup (culture); } - if (token strncmp (token, null, 4) != 0) + if (token strncmp (token, null, 4) != 0) { + if (strlen (token) != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) + return FALSE; + g_strlcpy ((char*)aname-public_key_token, token, MONO_PUBLIC_KEY_TOKEN_LENGTH); + } + + if (key strncmp (key, null, 4) != 0) { + gchar *arr, *tok, *encoded; + int i, j; + + if (strlen (key) != MONO_PUBLIC_KEY_LENGTH) + return FALSE; Can't the length change based on the flags? Sebastien? The structure is a CryptoAPI blob who's size change only if the key length change. However strongnames can now be bigger than 1024 bits (on 2.0). We don't support that (yet) and we'll have to change some assumptions in the code to do so. Anyway we better start now... Note: but this shouldn't affect the public key tokens -- Sebastien ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list
Re: [Mono-dev] [Patch] AssemblyName ctor (yes, again)
This break the ABI: is_version_defined is not needed since you can check the fields anyway. is_persistent can go away some other way (for example by always having public_key allocated, but it would be better to find another which doesn't make us waste memory). No, you can't check the fields. If Version is defined as 0.0.0.0, or if the user didn't specified version, it happens the same. Then Version is created for AssemblyName calling the new ctor, even when it wasn't specified (not compatible with .Net). However, since it could break api, as you mentioned maybe we should find other way to do it (and also change the persistent flag). Carlos. ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list
Re: [Mono-dev] [Patch] AssemblyName ctor
Hey, I didn't take the choice of using the internal call (unamnaged code) since I thought it was not optimal (Paolo's told me that was not true). About the other point, I hadn't thought about it (using the same function to provide the same behavior for all the possible uses). So I will be using the internal call and will see if we need changes there. Thanks for the reply, Carlos. ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list
Re: [Mono-dev] [Patch] AssemblyName ctor
Hey Paolo, We have mono_assembly_name_parse, which receives a MonoString* and a MonoAssemblyName*. The problem I find is that every time a System.Reflection.AssemblyName were created using the described ctor, we should also create a MonoAssemblyName (not needed). With the managed ctor, we also avoid calling the internal call. What do you think? Carlos. El sáb, 20-08-2005 a las 12:27 +0200, Paolo Molaro escribió: On 08/19/05 Carlos Alberto Cortez wrote: The patch attached implements the new AssemblyName ctor without using internal calls. Could anybody review it? And the advantage of this is? The runtime needs and does have a function to do the parsing of the string, so just use an icall to use that. lupus ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list
Re: [Mono-dev] [Patch] AssemblyName ctor
There is a case-insensitive ordinal compare in .Net 2.0 that you should use. If you use InvariantCulture you get a linguistic comparison based on the invariant culture. However these strings don't look like any natural language text that needs natural language processing. It will also construct the whole ICU4C and possibly ICU libraries, which is extremely costly. I really whish MS would have made two string classes in the first place: String and LanguageString Andreas - Original Message - From: Carlos Alberto Cortez [EMAIL PROTECTED] To: Andreas Nahr [EMAIL PROTECTED] Cc: Mono Devel mono-devel-list@lists.ximian.com Sent: Saturday, August 20, 2005 12:34 AM Subject: Re: [Mono-dev] [Patch] AssemblyName ctor Hello again, comments below: + if (String.Compare (parts [i], 0, Version=, 0, 8, true, CultureInfo.InvariantCulture) == 0) This is most likely incorrect and needs to use an ordinal comparison, no InvariantCulture (used more than one time) I'm not sure that's correct. I tested in .Net and we requiere insensitive comparison, not ordinal ones (as far I understood). So I think I'll keep it this way. Carlos. ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list
Re: [Mono-dev] [Patch] AssemblyName ctor
Hey, The patch attached implements the new AssemblyName ctor without using internal calls. Could anybody review it? +int GetCharNumericValue (char c) +{ +if (c = (char)0x30 c = (char)0x3B) +return c - 0x30; // 0-9 +if (c = (char)0x61 c = (char)0x66) +return c - 0x57; // a-f 1) Why not use '0' rather than (char)0x30 2) What about uppercase hex? +} catch { +throw new FileLoadException (The assembly name is invalid.); +} It might be helpful to say catch (Exception e) { throw FileLoadException (..., e) }, so that the developer gets a possibly helpful message. +for (int i = 0; i parts.Length; i++) { foreach (string s in parts); + if (String.Compare (parts [i], 0, Version=, 0, 8, true, CultureInfo.InvariantCulture) == 0) +version = new Version (parts [i].Substring (8, parts [i].Length - 8)); If Version= (or any other thing) occurs twice, what happens? NUnit tests? -- Ben ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list
Re: [Mono-dev] [Patch] AssemblyName ctor
Hello again, comments below: + if (String.Compare (parts [i], 0, Version=, 0, 8, true, CultureInfo.InvariantCulture) == 0) This is most likely incorrect and needs to use an ordinal comparison, no InvariantCulture (used more than one time) I'm not sure that's correct. I tested in .Net and we requiere insensitive comparison, not ordinal ones (as far I understood). So I think I'll keep it this way. Carlos. ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list
Re: [Mono-dev] [Patch] AssemblyName ctor
Look at this one: http://msdn2.microsoft.com/library/k13t5kxe(en-us,vs.80).aspx This is ordinal and case-insensitive all in one. It requires .NET 2.0 but the constructor is 2.0-only so this is not a problem. String.Compare with ignore case matches a lot of cases that are considered equal for linguistic reasons but should not be considered equal for case-insensitive ordinal comparsion. Kornél - Original Message - From: Carlos Alberto Cortez [EMAIL PROTECTED] To: Andreas Nahr [EMAIL PROTECTED] Cc: Mono Devel mono-devel-list@lists.ximian.com Sent: Saturday, August 20, 2005 12:34 AM Subject: Re: [Mono-dev] [Patch] AssemblyName ctor Hello again, comments below: + if (String.Compare (parts [i], 0, Version=, 0, 8, true, CultureInfo.InvariantCulture) == 0) This is most likely incorrect and needs to use an ordinal comparison, no InvariantCulture (used more than one time) I'm not sure that's correct. I tested in .Net and we requiere insensitive comparison, not ordinal ones (as far I understood). So I think I'll keep it this way. Carlos. ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list
[Mono-dev] [Patch] AssemblyName ctor (fixed)
Hey, The attached patch contains the latest suggestions of both Kornel and Ben. Maybe the only thing to be noted is that I kept the hexadecimal notation when comparing chars, since the same is used in Char.GetNumericalValue (). New tests are also attached, and run fine under .Net 2.0 Carlos. Index: AssemblyName.cs === --- AssemblyName.cs (revisión: 48583) +++ AssemblyName.cs (copia de trabajo) @@ -37,6 +37,8 @@ using System.Text; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; +using System.IO; +using System.Collections.Generic; using Mono.Security; @@ -73,7 +75,6 @@ int processor_architecture; #endif #endregion - public AssemblyName () { // defaults @@ -81,11 +82,102 @@ } #if NET_2_0 + const string exceptionMessage = The assembly name is invalid.; + public AssemblyName (string assemblyName) { - name = assemblyName; + string [] parts; + + if (assemblyName == null) +throw new ArgumentNullException (assemblyName); + if (assemblyName.Length 1) +throw new ArgumentException (assemblyName cannot have zero length, assemblyName); + + parts = assemblyName.Split (','); + name = parts [0].Trim (); + if (name.Length 1) +throw new FileLoadException (exceptionMessage); + + IComparerstring comparer = StringComparer.OrdinalIgnoreCase; + for (int i = 1; i parts.Length; i++) { +if (parts [i].IndexOf ('=') 0) + throw new FileLoadException (exceptionMessage); + +string [] values = parts [i].Split ('='); +values [0] = values [0].Trim (); +values [1] = values [1].Trim (); +if (values [0].Length 1 || values [1].Length 1) + throw new FileLoadException (exceptionMessage); + +if (comparer.Compare (values [0], Version) == 0) { + if (version != null) + throw new FileLoadException (exceptionMessage); + try { + version = new Version (values [1]); + } catch (ArgumentException) { + throw new FileLoadException (exceptionMessage); + } catch (FormatException) { + throw new FileLoadException (exceptionMessage); + } +} else if (comparer.Compare (values [0], Culture) == 0) { + if (cultureinfo != null) + throw new FileLoadException (exceptionMessage); + if (comparer.Compare (values [1], neutral) == 0) + values [1] = ; + cultureinfo = new CultureInfo (values [1]); +} else if (comparer.Compare (values [0], PublicKeyToken) == 0) { + if (keyToken != null) + throw new FileLoadException (exceptionMessage); + ParsePublicKeyToken (values [1]); +} else if (comparer.Compare (values [0], PublicKey) == 0) { + if (publicKey != null) + throw new FileLoadException (exceptionMessage); + ParsePublicKey (values [1]); +} else + throw new FileLoadException (exceptionMessage); + } + } + void ParsePublicKeyToken (string kToken) + { + if (kToken.Length != 16) +throw new FileLoadException (exceptionMessage); + + keyToken = new byte [8]; + for (int i = 0, j = 0; i 8; i++) { +keyToken [i] = (byte) (GetCharNumericValue (kToken [j++]) 4); +keyToken [i] |= (byte) GetCharNumericValue (kToken [j++]); + } + } + + void ParsePublicKey (string key) + { + if (key.Length != 320) +throw new FileLoadException (exceptionMessage); + + publicKey = new byte [160]; + for (int i = 0, j = 0; i 160; i++) { +publicKey [i] = (byte) (GetCharNumericValue (key [j++]) 4); +publicKey [i] |= (byte) GetCharNumericValue (key [j++]); + } + flags = AssemblyNameFlags.PublicKey; + } + + int GetCharNumericValue (char c) + { + if (c = (char)0x30 c = (char)0x3B) +return c - 0x30; // 0-9 + if (c = (char)0x41 c = (char)0x46) +return c - 0x37; // A-F + if (c = (char)0x61 c = (char)0x66) +return c - 0x57; // a-f + + throw new FileLoadException (exceptionMessage); + } +#endif + +#if NET_2_0 [MonoTODO] public ProcessorArchitecture ProcessorArchitecture { get { Index: AssemblyNameTest.cs === --- AssemblyNameTest.cs (revisión: 48583) +++ AssemblyNameTest.cs (copia de trabajo) @@ -531,6 +531,228 @@ } return tokenString; } + +#if NET_2_0 + [Test] + public void Ctor1 () + { + const string assemblyName = TestAssembly; + AssemblyName an = new AssemblyName (assemblyName); + Assert.IsNotNull (an.Name, Ctor1#1); + Assert.AreEqual (an.Name, assemblyName, Ctor1#2); + } + + [Test] + public void Ctor2 () + { + const string assemblyName = TestAssembly; + const string assemblyVersion = 1.2.3.4; + AssemblyName an = new AssemblyName (assemblyName + , Version= + assemblyVersion); + Assert.IsNotNull (an.Name, Ctor2#1); + Assert.AreEqual (an.Name, assemblyName, Ctor2#2); + Assert.IsNotNull (an.Version, Ctor2#3); + Assert.AreEqual (an.Version, new Version (assemblyVersion), Ctor2#4); + } + + [Test] + public void Ctor3 () + { + const
Re: [Mono-dev] [Patch] AssemblyName ctor (correction)
On 08/09/05 Carlos Alberto Cortez wrote: +static void +ves_icall_System_Reflection_AssemblyName_InternalParseKeyToken (MonoReflectionAssemblyName *aname, MonoString *key_token) +{ + char *p, *token; + int i, j; + + token = mono_string_to_utf8 (key_token); + aname-keyToken = mono_array_new (mono_domain_get (), mono_defaults.byte_class, 8); + p = mono_array_addr (aname-keyToken, char, 0); + for (i = 0, j = 0; i 8; i++) { + *p = g_ascii_xdigit_value (token [j++]) 4; + *p |= g_ascii_xdigit_value (token [j++]); + p++; + } + + g_free (token); I see no need to implement either of the two methods as internal calls. Use C# code. lupus -- - [EMAIL PROTECTED] debian/rules [EMAIL PROTECTED] Monkeys do it better ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list
[Mono-dev] [Patch] AssemblyName ctor
hey, Currently the AssemblyName (string) ctor is not implemented to receive the long format assembly name (such MyAssembly, Version=1.2,...). The attached patch adds support for it. Some tests are also attached. Carlos. Index: icall.c === --- icall.c (revisión: 48211) +++ icall.c (copia de trabajo) @@ -3730,6 +3730,44 @@ return result; } +static void +ves_icall_System_Reflection_AssemblyName_InternalParseKeyToken (MonoReflectionAssemblyName *aname, MonoString *key_token) +{ + char *p, *token; + int i, j; + + token = mono_string_to_utf8 (key_token); + aname-keyToken = mono_array_new (mono_domain_get (), mono_defaults.byte_class, 8); + p = mono_array_addr (aname-keyToken, char, 0); + for (i = 0, j = 0; i 8; i++) { + *p = g_ascii_xdigit_value (token [j++]) 4; + *p |= g_ascii_xdigit_value (token [j++]); + p++; + } + + g_free (token); +} + +static void +ves_icall_System_Reflection_AssemblyName_InternalParseKey (MonoReflectionAssemblyName *aname, MonoString *public_key) +{ + char *p, *key; + int pkey_len, i, j; + + key = mono_string_to_utf8 (public_key); + pkey_len = mono_string_length (public_key) / 2; // Format used in .Net + + aname-publicKey = mono_array_new (mono_domain_get (), mono_defaults.byte_class, pkey_len); + p = mono_array_addr (aname-publicKey, char, 0); + for (i = 0, j = 0; i pkey_len; i++) { + *p = g_ascii_xdigit_value (key [j++]) 4; + *p |= g_ascii_xdigit_value (key [j++]); + p++; + } + + g_free (key); +} + typedef struct { MonoArray *res; int idx; @@ -6510,6 +6548,11 @@ {load_with_partial_name, ves_icall_System_Reflection_Assembly_load_with_partial_name} }; +static const IcallEntry assembly_name_icalls [] = { + {InternalParseKey, ves_icall_System_Reflection_AssemblyName_InternalParseKey}, + {InternalParseKeyToken, ves_icall_System_Reflection_AssemblyName_InternalParseKeyToken} +}; + static const IcallEntry methodbase_icalls [] = { {GetCurrentMethod, ves_icall_GetCurrentMethod}, {GetMethodBodyInternal, ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal}, @@ -7046,6 +7089,7 @@ {System.Net.Sockets.SocketException, socketex_icalls, G_N_ELEMENTS (socketex_icalls)}, {System.Object, object_icalls, G_N_ELEMENTS (object_icalls)}, {System.Reflection.Assembly, assembly_icalls, G_N_ELEMENTS (assembly_icalls)}, + {System.Reflection.AssemblyName, assembly_name_icalls, G_N_ELEMENTS (assembly_name_icalls)}, {System.Reflection.Emit.AssemblyBuilder, assemblybuilder_icalls, G_N_ELEMENTS (assemblybuilder_icalls)}, {System.Reflection.Emit.CustomAttributeBuilder, customattrbuilder_icalls, G_N_ELEMENTS (customattrbuilder_icalls)}, {System.Reflection.Emit.DynamicMethod, dynamicmethod_icalls, G_N_ELEMENTS (dynamicmethod_icalls)}, ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list
[Mono-dev] [Patch] AssemblyName ctor (correction)
In the last message some attachments were missing. All of them are now correctly attached. Index: AssemblyName.cs === --- AssemblyName.cs (revisión: 48211) +++ AssemblyName.cs (copia de trabajo) @@ -37,6 +37,7 @@ using System.Text; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; +using System.IO; using Mono.Security; @@ -73,6 +74,7 @@ int processor_architecture; #endif #endregion + static readonly char [] delimiter = {','}; public AssemblyName () { @@ -83,9 +85,64 @@ #if NET_2_0 public AssemblyName (string assemblyName) { - name = assemblyName; + string [] parts; + + if (assemblyName == null) +throw new ArgumentNullException (assemblyName); + if (assemblyName == ) +throw new ArgumentException (assemblyName cannot have zero length, assemblyName); + + // Remove white spaces, to mimic .Net behavior + assemblyName = assemblyName.Replace ( , ); + parts = assemblyName.Split (delimiter); + if (parts [0] == ) +throw new FileLoadException (The assembly name is invalid.); + + name = parts [0]; + for (int i = 0; i parts.Length; i++) { +try { + if (String.Compare (parts [i], 0, Version=, 0, 8, true, CultureInfo.InvariantCulture) == 0) + version = new Version (parts [i].Substring (8, parts [i].Length - 8)); + else if (String.Compare (parts [i], 0, Culture=, 0, 8, true, CultureInfo.InvariantCulture) == 0) { + string culture = parts [i].Substring (8, parts [i].Length - 8); + if (String.Compare (culture, neutral, true, CultureInfo.InvariantCulture) == 0) + culture = ; + cultureinfo = new CultureInfo (culture); + } + else if (String.Compare (parts [i], 0, PublicKeyToken=, 0, 15, true, CultureInfo.InvariantCulture) == 0) + ParseKeyToken (parts [i].Substring (15, parts [i].Length - 15)); + else if (String.Compare (parts [i], 0, PublicKey=, 0, 10, true, CultureInfo.InvariantCulture) == 0) + ParseKey (parts [i].Substring (10, parts [i].Length - 10)); +} catch { + throw new FileLoadException (The assembly name is invalid.); +} + } + } + [MethodImpl (MethodImplOptions.InternalCall)] + extern void InternalParseKeyToken (string keyToken); + + void ParseKeyToken (string kToken) + { + if (kToken.Length != 16) +throw new Exception (); + + InternalParseKeyToken (kToken); + } + + [MethodImpl (MethodImplOptions.InternalCall)] + extern void InternalParseKey (string key); + + void ParseKey (string key) + { + if (key.Length != 320) +throw new Exception (); + + flags = AssemblyNameFlags.PublicKey; + InternalParseKey (key); + } + [MonoTODO] public ProcessorArchitecture ProcessorArchitecture { get { Index: AssemblyNameTest.cs === --- AssemblyNameTest.cs (revisión: 48211) +++ AssemblyNameTest.cs (copia de trabajo) @@ -19,6 +19,7 @@ using System.Globalization; using System.Runtime.Serialization.Formatters.Binary; using System.Security; +using System.Text; namespace MonoTests.System.Reflection { @@ -531,6 +532,73 @@ } return tokenString; } + +#if NET_2_0 + [Test] + public void Ctor1 () + { + const string assemblyName = TestAssembly; + AssemblyName an = new AssemblyName (assemblyName); + Assert.IsNotNull (an.Name, Ctor1#1); + Assert.AreEqual (an.Name, assemblyName, Ctor1#2); + } + + [Test] + public void Ctor2 () + { + const string assemblyName = TestAssembly; + const string assemblyVersion = 1.2; + AssemblyName an = new AssemblyName (assemblyName + , Version= + assemblyVersion); + Assert.IsNotNull (an.Name, Ctor2#1); + Assert.AreEqual (an.Name, assemblyName, Ctor2#2); + Assert.IsNotNull (an.Version, Ctor2#3); + Assert.AreEqual (an.Version, new Version (assemblyVersion), Ctor2#4); + } + + [Test] + public void Ctor3 () + { + const string assemblyName = TestAssembly; + const string assemblyCulture = en-US; + AssemblyName an = new AssemblyName (assemblyName + , Culture= + assemblyCulture); + Assert.IsNotNull (an.Name, Ctor3#1); + Assert.AreEqual (an.Name, assemblyName, Ctor3#2); + Assert.IsNotNull (an.CultureInfo, Ctor3#3); + Assert.AreEqual (an.CultureInfo, new CultureInfo (assemblyCulture), Ctor3#4); + } + + [Test] + public void Ctor4 () + { + const string assemblyName = TestAssembly; + byte [] assemblyKeyToken; + AssemblyName an = new AssemblyName (assemblyName + , PublicKeyToken= + GetTokenString (token)); + Assert.IsNotNull (an.Name, Ctor4#1); + Assert.AreEqual (an.Name, assemblyName, Ctor4#2); + Assert.IsNotNull (assemblyKeyToken = an.GetPublicKeyToken (), Ctor4#3); + Assert.AreEqual (assemblyKeyToken, token, Ctor4#4); + } + + [Test] + public void Ctor5 () + { + const string assemblyName = TestAssembly; + const string assemblyCulture = neutral; + const string assemblyVersion = 1.2.3.4; + byte [] assemblyKeyToken; + + AssemblyName an = new