Delete unmanaged AssemblyName parser (#68737)
authorJan Kotas <jkotas@microsoft.com>
Tue, 3 May 2022 03:35:43 +0000 (20:35 -0700)
committerGitHub <noreply@github.com>
Tue, 3 May 2022 03:35:43 +0000 (20:35 -0700)
Replaced the few places that need to parse assembly names in the VM with callbacks to CoreLib

31 files changed:
src/coreclr/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs
src/coreclr/binder/CMakeLists.txt
src/coreclr/binder/applicationcontext.cpp
src/coreclr/binder/assemblyidentitycache.cpp [deleted file]
src/coreclr/binder/inc/applicationcontext.hpp
src/coreclr/binder/inc/assemblybindercommon.hpp
src/coreclr/binder/inc/assemblyidentity.hpp
src/coreclr/binder/inc/assemblyidentitycache.hpp [deleted file]
src/coreclr/binder/inc/stringlexer.hpp [deleted file]
src/coreclr/binder/inc/stringlexer.inl [deleted file]
src/coreclr/binder/inc/textualidentityparser.hpp
src/coreclr/binder/stringlexer.cpp [deleted file]
src/coreclr/binder/textualidentityparser.cpp
src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj
src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.cs [deleted file]
src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs
src/coreclr/vm/assembly.cpp
src/coreclr/vm/assemblynative.hpp
src/coreclr/vm/baseassemblyspec.cpp
src/coreclr/vm/baseassemblyspec.h
src/coreclr/vm/baseassemblyspec.inl
src/coreclr/vm/coreassemblyspec.cpp
src/coreclr/vm/corelib.h
src/coreclr/vm/corhost.cpp
src/coreclr/vm/metasig.h
src/coreclr/vm/multicorejitplayer.cpp
src/coreclr/vm/nativelibrary.cpp
src/coreclr/vm/qcallentrypoints.cpp
src/coreclr/vm/typeparse.cpp
src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs
src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs

index fc3a0a6..6d02f9d 100644 (file)
@@ -3,9 +3,8 @@
 
 using System.Configuration.Assemblies;
 using System.Globalization;
-using System.IO;
 using System.Runtime.CompilerServices;
-using System.Runtime.Serialization;
+using System.Runtime.InteropServices;
 
 namespace System.Reflection
 {
@@ -61,7 +60,7 @@ namespace System.Reflection
         }
     }
 
-    public sealed partial class AssemblyName : ICloneable, IDeserializationCallback, ISerializable
+    public sealed partial class AssemblyName
     {
         internal unsafe AssemblyName(NativeAssemblyNameParts* pParts)
             : this()
@@ -149,5 +148,31 @@ namespace System.Reflection
             }
             return ProcessorArchitecture.None;
         }
+
+        private static unsafe void ParseAsAssemblySpec(char* pAssemblyName, void* pAssemblySpec)
+        {
+            AssemblyNameParser.AssemblyNameParts parts = AssemblyNameParser.Parse(MemoryMarshal.CreateReadOnlySpanFromNullTerminated(pAssemblyName));
+
+            fixed (char* pName = parts._name)
+            fixed (char* pCultureName = parts._cultureName)
+            fixed (byte* pPublicKeyOrToken = parts._publicKeyOrToken)
+            {
+                NativeAssemblyNameParts nameParts = default;
+
+                nameParts._flags = parts._flags;
+                nameParts._pName = pName;
+                nameParts._pCultureName = pCultureName;
+
+                nameParts._pPublicKeyOrToken = pPublicKeyOrToken;
+                nameParts._cbPublicKeyOrToken = (parts._publicKeyOrToken != null) ? parts._publicKeyOrToken.Length : 0;
+
+                nameParts.SetVersion(parts._version, defaultValue: ushort.MaxValue);
+
+                InitializeAssemblySpec(&nameParts, pAssemblySpec);
+            }
+        }
+
+        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyName_InitializeAssemblySpec")]
+        private static unsafe partial void InitializeAssemblySpec(NativeAssemblyNameParts* pAssemblyNameParts, void* pAssemblySpec);
     }
 }
index 1885ea1..b04b4b8 100644 (file)
@@ -7,12 +7,10 @@ set(BINDER_COMMON_SOURCES
     applicationcontext.cpp
     assembly.cpp
     assemblybindercommon.cpp
-    assemblyidentitycache.cpp
     assemblyname.cpp
     bindertracing.cpp
     defaultassemblybinder.cpp
     failurecache.cpp
-    stringlexer.cpp
     textualidentityparser.cpp
     utils.cpp
 )
@@ -26,7 +24,6 @@ set(BINDER_COMMON_HEADERS
     inc/assemblyentry.hpp
     inc/assemblyhashtraits.hpp
     inc/assemblyidentity.hpp
-    inc/assemblyidentitycache.hpp
     inc/assemblyname.hpp
     inc/assemblyname.inl
     inc/assemblyversion.hpp
@@ -40,8 +37,6 @@ set(BINDER_COMMON_HEADERS
     inc/failurecachehashtraits.hpp
     inc/loadcontext.hpp
     inc/loadcontext.inl
-    inc/stringlexer.hpp
-    inc/stringlexer.inl
     inc/textualidentityparser.hpp
     inc/utils.hpp
 )
index 28ba1c1..11369b8 100644 (file)
@@ -15,7 +15,6 @@
 #include "stringarraylist.h"
 #include "loadcontext.hpp"
 #include "failurecache.hpp"
-#include "assemblyidentitycache.hpp"
 #include "utils.hpp"
 #include "ex.h"
 #include "clr/fs/path.h"
@@ -216,39 +215,6 @@ namespace BINDER_SPACE
         return hr;
     }
 
-    HRESULT ApplicationContext::GetAssemblyIdentity(LPCSTR                 szTextualIdentity,
-                                                    AssemblyIdentityUTF8 **ppAssemblyIdentity)
-    {
-        HRESULT hr = S_OK;
-
-        _ASSERTE(szTextualIdentity != NULL);
-        _ASSERTE(ppAssemblyIdentity != NULL);
-
-        CRITSEC_Holder contextLock(GetCriticalSectionCookie());
-
-        AssemblyIdentityUTF8 *pAssemblyIdentity = m_assemblyIdentityCache.Lookup(szTextualIdentity);
-        if (pAssemblyIdentity == NULL)
-        {
-            NewHolder<AssemblyIdentityUTF8> pNewAssemblyIdentity;
-            SString sTextualIdentity;
-
-            SAFE_NEW(pNewAssemblyIdentity, AssemblyIdentityUTF8);
-            sTextualIdentity.SetUTF8(szTextualIdentity);
-
-            IF_FAIL_GO(TextualIdentityParser::Parse(sTextualIdentity, pNewAssemblyIdentity));
-            IF_FAIL_GO(m_assemblyIdentityCache.Add(szTextualIdentity, pNewAssemblyIdentity));
-
-            pNewAssemblyIdentity->PopulateUTF8Fields();
-
-            pAssemblyIdentity = pNewAssemblyIdentity.Extract();
-        }
-
-        *ppAssemblyIdentity = pAssemblyIdentity;
-
-    Exit:
-        return hr;
-    }
-
     bool ApplicationContext::IsTpaListProvided()
     {
         return m_pTrustedPlatformAssemblyMap != nullptr;
diff --git a/src/coreclr/binder/assemblyidentitycache.cpp b/src/coreclr/binder/assemblyidentitycache.cpp
deleted file mode 100644 (file)
index bff89d1..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ============================================================
-//
-// AssemblyIdentityCache.cpp
-//
-
-
-//
-// Implements the AssemblyIdentityCache class
-//
-// ============================================================
-
-#include "assemblyidentitycache.hpp"
-
-namespace BINDER_SPACE
-{
-    AssemblyIdentityCache::AssemblyIdentityCache() : SHash<AssemblyIdentityHashTraits>::SHash()
-    {
-        // Nothing to do here
-    }
-
-    AssemblyIdentityCache::~AssemblyIdentityCache()
-    {
-        // Delete entries and contents array
-        for (Hash::Iterator i = Hash::Begin(), end = Hash::End(); i != end; i++)
-        {
-            const AssemblyIdentityCacheEntry *pAssemblyIdentityCacheEntry = *i;
-            delete pAssemblyIdentityCacheEntry;
-        }
-        RemoveAll();
-    }
-
-    HRESULT AssemblyIdentityCache::Add(LPCSTR                szTextualIdentity,
-                                       AssemblyIdentityUTF8 *pAssemblyIdentity)
-    {
-        HRESULT hr = S_OK;
-
-        NewHolder<AssemblyIdentityCacheEntry> pAssemblyIdentityCacheEntry;
-        SAFE_NEW(pAssemblyIdentityCacheEntry, AssemblyIdentityCacheEntry);
-
-        pAssemblyIdentityCacheEntry->SetTextualIdentity(szTextualIdentity);
-        pAssemblyIdentityCacheEntry->SetAssemblyIdentity(pAssemblyIdentity);
-
-        Hash::Add(pAssemblyIdentityCacheEntry);
-        pAssemblyIdentityCacheEntry.SuppressRelease();
-
-    Exit:
-        return hr;
-    }
-
-    AssemblyIdentityUTF8 *AssemblyIdentityCache::Lookup(LPCSTR szTextualIdentity)
-    {
-        AssemblyIdentityUTF8 *pAssemblyIdentity = NULL;
-        AssemblyIdentityCacheEntry *pAssemblyIdentityCacheEntry = Hash::Lookup(szTextualIdentity);
-
-        if (pAssemblyIdentityCacheEntry != NULL)
-        {
-            pAssemblyIdentity = pAssemblyIdentityCacheEntry->GetAssemblyIdentity();
-        }
-
-        return pAssemblyIdentity;
-    }
-};
index 9364c7e..44d9155 100644 (file)
@@ -16,7 +16,6 @@
 
 #include "bindertypes.hpp"
 #include "failurecache.hpp"
-#include "assemblyidentitycache.hpp"
 #include "stringarraylist.h"
 
 namespace BINDER_SPACE
@@ -94,9 +93,6 @@ namespace BINDER_SPACE
                                   /* in */ SString &sAppPaths,
                                   /* in */ BOOL     fAcquireLock);
 
-        HRESULT GetAssemblyIdentity(/* in */ LPCSTR                szTextualIdentity,
-                                    /* in */ AssemblyIdentityUTF8 **ppAssemblyIdentity);
-
         // Getters/Setter
         inline ExecutionContext *GetExecutionContext();
         inline FailureCache *GetFailureCache();
@@ -119,8 +115,6 @@ namespace BINDER_SPACE
         FailureCache      *m_pFailureCache;
         CRITSEC_COOKIE     m_contextCS;
 
-        AssemblyIdentityCache m_assemblyIdentityCache;
-
         StringArrayList    m_platformResourceRoots;
         StringArrayList    m_appPaths;
 
index 8fd4358..b3b2158 100644 (file)
@@ -25,8 +25,6 @@ class PEImage;
 
 namespace BINDER_SPACE
 {
-    class AssemblyIdentityUTF8;
-
     class AssemblyBinderCommon
     {
     public:
index ef4768d..4372357 100644 (file)
@@ -81,49 +81,6 @@ namespace BINDER_SPACE
         AssemblyContentType m_kContentType;
         DWORD               m_dwIdentityFlags;
     };
-
-    class AssemblyIdentityUTF8 final : public AssemblyIdentity
-    {
-    public:
-        AssemblyIdentityUTF8()
-        {
-            m_szSimpleNameUTF8 = NULL;
-            m_szCultureOrLanguageUTF8 = NULL;
-        }
-
-        void PopulateUTF8Fields()
-        {
-            m_szSimpleNameUTF8 = m_simpleName.GetUTF8(sSimpleNameBuffer);
-
-            if (Have(IDENTITY_FLAG_CULTURE) && !m_cultureOrLanguage.IsEmpty())
-            {
-                m_szCultureOrLanguageUTF8 = m_cultureOrLanguage.GetUTF8(sCultureBuffer);
-            }
-        }
-
-        inline LPCSTR GetSimpleNameUTF8()
-        {
-            return m_szSimpleNameUTF8;
-        }
-
-        inline LPCSTR GetCultureOrLanguageUTF8()
-        {
-            return m_szCultureOrLanguageUTF8;
-        }
-
-        inline const BYTE *GetPublicKeyOrTokenArray()
-        {
-            const BYTE *pPublicKeyOrToken = m_publicKeyOrTokenBLOB;
-
-            return pPublicKeyOrToken;
-        }
-
-    protected:
-        StackScratchBuffer sSimpleNameBuffer;
-        StackScratchBuffer sCultureBuffer;
-        LPCSTR m_szSimpleNameUTF8;
-        LPCSTR m_szCultureOrLanguageUTF8;
-    };
 };
 
 #endif
diff --git a/src/coreclr/binder/inc/assemblyidentitycache.hpp b/src/coreclr/binder/inc/assemblyidentitycache.hpp
deleted file mode 100644 (file)
index 86e70f4..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ============================================================
-//
-// AssemblyIdentityCache.hpp
-//
-
-
-//
-// Defines the AssemblyIdentityCache class and its helpers
-//
-// ============================================================
-
-#ifndef __BINDER__ASSEMBLY_IDENTITY_CACHE_HPP__
-#define __BINDER__ASSEMBLY_IDENTITY_CACHE_HPP__
-
-#include "bindertypes.hpp"
-#include "assemblyidentity.hpp"
-#include "sstring.h"
-#include "shash.h"
-
-namespace BINDER_SPACE
-{
-    class AssemblyIdentityCacheEntry
-    {
-    public:
-        inline AssemblyIdentityCacheEntry()
-        {
-            m_szTextualIdentity = NULL;
-            m_pAssemblyIdentity = NULL;
-        }
-        inline ~AssemblyIdentityCacheEntry()
-        {
-            SAFE_DELETE_ARRAY(m_szTextualIdentity);
-            SAFE_DELETE(m_pAssemblyIdentity);
-        }
-
-        // Getters/Setters
-        inline LPCSTR GetTextualIdentity()
-        {
-            return m_szTextualIdentity;
-        }
-        inline void SetTextualIdentity(LPCSTR szTextualIdentity)
-        {
-            size_t len = strlen(szTextualIdentity) + 1;
-
-            m_szTextualIdentity = new char[len];
-            strcpy_s((LPSTR) m_szTextualIdentity, len, szTextualIdentity);
-        }
-        inline AssemblyIdentityUTF8 *GetAssemblyIdentity()
-        {
-            return m_pAssemblyIdentity;
-        }
-        inline void SetAssemblyIdentity(AssemblyIdentityUTF8 *pAssemblyIdentity)
-        {
-            m_pAssemblyIdentity = pAssemblyIdentity;
-        }
-
-    protected:
-        LPCSTR                m_szTextualIdentity;
-        AssemblyIdentityUTF8 *m_pAssemblyIdentity;
-    };
-
-    class AssemblyIdentityHashTraits : public DefaultSHashTraits<AssemblyIdentityCacheEntry *>
-    {
-    public:
-        typedef LPCSTR key_t;
-
-        static key_t GetKey(element_t pAssemblyIdentityCacheEntry)
-        {
-            return pAssemblyIdentityCacheEntry->GetTextualIdentity();
-        }
-        static BOOL Equals(key_t textualIdentity1, key_t textualIdentity2)
-        {
-            if ((textualIdentity1 == NULL) && (textualIdentity2 == NULL))
-                return TRUE;
-            if ((textualIdentity1 == NULL) || (textualIdentity2 == NULL))
-                return FALSE;
-
-            return (strcmp(textualIdentity1, textualIdentity2) == 0);
-        }
-        static count_t Hash(key_t textualIdentity)
-        {
-            if (textualIdentity == NULL)
-                return 0;
-            else
-                return HashStringA(textualIdentity);
-        }
-        static element_t Null()
-        {
-            return NULL;
-        }
-        static bool IsNull(const element_t &assemblyIdentityCacheEntry)
-        {
-            return (assemblyIdentityCacheEntry == NULL);
-        }
-
-    };
-
-    class AssemblyIdentityCache : protected SHash<AssemblyIdentityHashTraits>
-    {
-    private:
-        typedef SHash<AssemblyIdentityHashTraits> Hash;
-    public:
-        AssemblyIdentityCache();
-        ~AssemblyIdentityCache();
-
-        HRESULT Add(/* in */ LPCSTR               szTextualIdentity,
-                    /* in */ AssemblyIdentityUTF8 *pAssemblyIdentity);
-        AssemblyIdentityUTF8 *Lookup(/* in */ LPCSTR szTextualIdentity);
-    };
-};
-
-#endif
diff --git a/src/coreclr/binder/inc/stringlexer.hpp b/src/coreclr/binder/inc/stringlexer.hpp
deleted file mode 100644 (file)
index f08e046..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ============================================================
-//
-// StringLexer.hpp
-//
-
-
-//
-// Defines the StringLexer class
-//
-// ============================================================
-
-#ifndef __BINDER__STRING_LEXER_HPP__
-#define __BINDER__STRING_LEXER_HPP__
-
-#include "bindertypes.hpp"
-
-#define GO_IF_NOT_EXPECTED(expr, kRequiredLexemeType)   \
-    if ((expr) != kRequiredLexemeType)                  \
-    {                                                   \
-        fIsValid = FALSE;                               \
-        goto Exit;                                      \
-    }
-
-#define GO_IF_END_OR_NOT_EXPECTED(expr, kRequiredLexemeType)            \
-    {                                                                   \
-        LEXEME_TYPE kGotLexemeType = (expr);                            \
-        if (kGotLexemeType == LEXEME_TYPE_END_OF_STREAM)                \
-        {                                                               \
-            goto Exit;                                                  \
-        }                                                               \
-        else                                                            \
-        {                                                               \
-            GO_IF_NOT_EXPECTED(kGotLexemeType, kRequiredLexemeType);    \
-        }                                                               \
-    }
-
-namespace BINDER_SPACE
-{
-    class StringLexer
-    {
-    public:
-        typedef enum
-        {
-            LEXEME_TYPE_INVALID,
-            LEXEME_TYPE_EQUALS,
-            LEXEME_TYPE_COMMA,
-            LEXEME_TYPE_COLON,
-            LEXEME_TYPE_SEMICOLON,
-            LEXEME_TYPE_STRING,
-            LEXEME_TYPE_END_OF_STREAM
-        } LEXEME_TYPE;
-
-        inline StringLexer();
-        inline ~StringLexer();
-
-        inline void Init(SString &inputString);
-
-        static inline BOOL IsWhitespace(WCHAR wcChar);
-        static inline BOOL IsEOS(WCHAR wcChar);
-        static inline BOOL IsQuoteCharacter(WCHAR wcChar);
-
-        BOOL IsSeparatorChar(WCHAR wcChar);
-        LEXEME_TYPE GetLexemeType(WCHAR wcChar);
-
-    protected:
-        static const WCHAR INVALID_CHARACTER = -1;
-
-        LEXEME_TYPE GetNextLexeme(SString &currentString);
-
-        inline WCHAR PopCharacter(BOOL *pfIsEscaped);
-        inline void PushCharacter(WCHAR wcCurrentChar,
-                                  BOOL fIsEscaped);
-
-        inline WCHAR GetRawCharacter();
-        inline WCHAR GetNextCharacter(BOOL *pfIsEscaped);
-
-        LEXEME_TYPE ParseString(SString &currentString);
-
-        void TrimTrailingWhiteSpaces(SString &currentString);
-
-        SString::Iterator m_cursor;
-        SString::Iterator m_end;
-
-        WCHAR m_wcCurrentChar;
-        BOOL m_fCurrentCharIsEscaped;
-    };
-
-#include "stringlexer.inl"
-};
-
-#endif
diff --git a/src/coreclr/binder/inc/stringlexer.inl b/src/coreclr/binder/inc/stringlexer.inl
deleted file mode 100644 (file)
index 42f7f73..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ============================================================
-//
-// StringLexer.inl
-//
-
-
-//
-// Implements the inlined methods of StringLexer class
-//
-// ============================================================
-
-#ifndef __BINDER__STRING_LEXER_INL__
-#define __BINDER__STRING_LEXER_INL__
-
-StringLexer::StringLexer()
-{
-    m_wcCurrentChar = INVALID_CHARACTER;
-    m_fCurrentCharIsEscaped = FALSE;
-}
-
-StringLexer::~StringLexer()
-{
-    // Nothing to do here
-}
-
-void StringLexer::Init(SString &inputString)
-{
-    m_cursor = inputString.Begin();
-    m_end = inputString.End();
-}
-
-BOOL StringLexer::IsWhitespace(WCHAR wcChar)
-{
-    return ((wcChar == L'\n') || (wcChar == L'\r') || (wcChar == L' ') || (wcChar == L'\t'));
-}
-
-BOOL StringLexer::IsEOS(WCHAR wcChar)
-{
-    return (wcChar == 0);
-}
-
-BOOL StringLexer::IsQuoteCharacter(WCHAR wcChar)
-{
-    return ((wcChar == L'\'') || (wcChar == L'"'));
-}
-
-WCHAR StringLexer::PopCharacter(BOOL *pfIsEscaped)
-{
-    WCHAR wcCurrentChar = m_wcCurrentChar;
-    if (wcCurrentChar != INVALID_CHARACTER)
-    {
-        m_wcCurrentChar = INVALID_CHARACTER;
-        *pfIsEscaped = m_fCurrentCharIsEscaped;
-        m_cursor++;
-    }
-    else
-    {
-        wcCurrentChar = GetNextCharacter(pfIsEscaped);
-    }
-
-    return wcCurrentChar;
-}
-
-void StringLexer::PushCharacter(WCHAR wcCurrentChar,
-                                BOOL  fIsEscaped)
-{
-    _ASSERTE(m_wcCurrentChar == INVALID_CHARACTER);
-
-    m_wcCurrentChar = wcCurrentChar;
-    m_fCurrentCharIsEscaped = fIsEscaped;
-    m_cursor--;
-}
-
-WCHAR StringLexer::GetRawCharacter()
-{
-    WCHAR wcCurrentChar = 0;
-
-    if (m_cursor < m_end)
-    {
-        wcCurrentChar = m_cursor[0];
-        m_cursor++;
-
-        // do not allow \0 anywhere in the string.
-        if (wcCurrentChar == 0)
-        {
-            wcCurrentChar = INVALID_CHARACTER;
-        }
-    }
-    else
-    {
-        // EOS
-        wcCurrentChar = 0;
-    }
-
-    return wcCurrentChar;
-}
-
-WCHAR StringLexer::GetNextCharacter(BOOL *pfIsEscaped)
-{
-    *pfIsEscaped = FALSE;
-
-    WCHAR wcCurrentChar = GetRawCharacter();
-    if (wcCurrentChar == L'\\')
-    {
-        WCHAR wcTempChar = GetRawCharacter();
-
-        // Handle standard escapes
-        switch (wcTempChar)
-        {
-        case L'"':
-        case L'\'':
-        case L',':
-        case L'\\':
-        case L'=':
-        case L't':
-        case L'n':
-        case L'r':
-            break;
-        default:
-            return INVALID_CHARACTER;
-        }
-
-        *pfIsEscaped = TRUE;
-        wcCurrentChar = wcTempChar;
-    }
-
-    return wcCurrentChar;
-}
-
-#endif
index 2b60c31..9802e57 100644 (file)
 #define __BINDER__TEXTUAL_IDENTITY_PARSER_HPP__
 
 #include "bindertypes.hpp"
-#include "stringlexer.hpp"
 
 namespace BINDER_SPACE
 {
     class AssemblyVersion;
     class AssemblyIdentity;
 
-    class TextualIdentityParser : public StringLexer
+    class TextualIdentityParser
     {
     public:
-        TextualIdentityParser(AssemblyIdentity *pAssemblyIdentity);
-        ~TextualIdentityParser();
-
-        static HRESULT Parse(/* in */  SString           &textualIdentity,
-                             /* out */ AssemblyIdentity *pAssemblyIdentity);
-
         static HRESULT ToString(/* in */  AssemblyIdentity *pAssemblyIdentity,
                                 /* in */  DWORD             dwIdentityFlags,
                                 /* out */ SString          &textualIdentity);
 
-        static BOOL ParseVersion(/* in */  SString &versionString,
-                                 /* out */ AssemblyVersion *pAssemblyVersion);
-
-        static BOOL HexToBlob(/* in */  SString &publicKeyOrToken,
-                              /* in */  BOOL     fValidateHex,
-                              /* in */  BOOL     fIsToken,
-                              /* out */ SBuffer &publicKeyOrTokenBLOB);
-
         static void BlobToHex(/* in */  SBuffer &publicKeyOrTokenBLOB,
                               /* out */ SString &publicKeyOrToken);
 
-        BOOL ParseString(/* in */  SString &textualString,
-                         /* out */ SString &contentString);
-
     protected:
-        BOOL Parse(/* in */  SString &textualIdentity);
-
-        BOOL PopulateAssemblyIdentity(/* in */ SString &attributeString,
-                                      /* in */ SString &valueString);
-
         static void EscapeString(/* in */ SString &input,
                                  /* out*/ SString &result);
-
-        AssemblyIdentity *m_pAssemblyIdentity;
-        DWORD m_dwAttributesSeen;
     };
 };
 
diff --git a/src/coreclr/binder/stringlexer.cpp b/src/coreclr/binder/stringlexer.cpp
deleted file mode 100644 (file)
index 44ec23e..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ============================================================
-//
-// StringLexer.cpp
-//
-
-
-//
-// Implements the StringLexer class
-//
-// ============================================================
-
-#include "stringlexer.hpp"
-#include "utils.hpp"
-
-#include "ex.h"
-
-namespace BINDER_SPACE
-{
-    StringLexer::LEXEME_TYPE
-    StringLexer::GetNextLexeme(SString &currentString)
-    {
-        BOOL fIsEscaped = FALSE;
-        WCHAR wcCurrentChar = INVALID_CHARACTER;
-
-        // Remove any white spaces
-        do
-        {
-            wcCurrentChar = PopCharacter(&fIsEscaped);
-        }
-        while (IsWhitespace(wcCurrentChar));
-
-        // Determine lexeme type
-        if (!fIsEscaped)
-        {
-            LEXEME_TYPE kLexemeType = GetLexemeType(wcCurrentChar);
-            if (kLexemeType != LEXEME_TYPE_STRING)
-            {
-                return kLexemeType;
-            }
-        }
-
-        // First character of string lexeme; push it back
-        PushCharacter(wcCurrentChar, fIsEscaped);
-        return ParseString(currentString);
-    }
-
-    StringLexer::LEXEME_TYPE
-    StringLexer::ParseString(SString &currentString)
-    {
-        BOOL fIsFirstCharacter = TRUE;
-        WCHAR wcCurrentChar = INVALID_CHARACTER;
-        WCHAR wcOpeningQuote = INVALID_CHARACTER;
-
-        currentString.Clear();
-
-        // Read until we find another lexeme that's not a string character
-        for (;;)
-        {
-            BOOL fIsEscaped = FALSE;
-            wcCurrentChar = PopCharacter(&fIsEscaped);
-
-            if (wcCurrentChar == INVALID_CHARACTER)
-            {
-                // Found invalid character encoding
-                return LEXEME_TYPE_INVALID;
-            }
-
-            if (IsEOS(wcCurrentChar))
-            {
-                if (IsQuoteCharacter(wcOpeningQuote))
-                {
-                    // EOS and unclosed quotes is an error
-                    return LEXEME_TYPE_INVALID;
-                }
-                else
-                {
-                    // Reached end of input and therefore of string
-                    break;
-                }
-            }
-
-            if (fIsFirstCharacter)
-            {
-                fIsFirstCharacter = FALSE;
-
-                // If first character is quote, then record its quoteness
-                if (IsQuoteCharacter(wcCurrentChar))
-                {
-                    wcOpeningQuote = wcCurrentChar;
-                    continue;
-                }
-            }
-
-            if (wcCurrentChar == wcOpeningQuote)
-            {
-                // We've found the closing quote for a quoted string
-                break;
-            }
-
-            if (!fIsEscaped && IsQuoteCharacter(wcCurrentChar) && !IsQuoteCharacter(wcOpeningQuote))
-            {
-                // Unescaped quotes in the middle of the string are an error
-                return LEXEME_TYPE_INVALID;
-            }
-
-            if (IsSeparatorChar(wcCurrentChar) && !IsQuoteCharacter(wcOpeningQuote) && !fIsEscaped)
-            {
-                // Unescaped separator char terminates the string
-                PushCharacter(wcCurrentChar, fIsEscaped);
-                break;
-            }
-
-            // Add character to current string
-            currentString.Append(wcCurrentChar);
-        }
-
-        if (!IsQuoteCharacter(wcOpeningQuote))
-        {
-            // Remove trailing white spaces from unquoted string
-            TrimTrailingWhiteSpaces(currentString);
-        }
-
-        return LEXEME_TYPE_STRING;
-    }
-
-    void StringLexer::TrimTrailingWhiteSpaces(SString &currentString)
-    {
-        SString::Iterator begin = currentString.Begin();
-        SString::Iterator cursor = currentString.End() - 1;
-        BOOL fFoundWhiteSpace = FALSE;
-
-        for (;;)
-        {
-            if ((cursor >= begin) && IsWhitespace(cursor[0]))
-            {
-                fFoundWhiteSpace = TRUE;
-                cursor--;
-                continue;
-            }
-            break;
-        }
-
-        if (fFoundWhiteSpace)
-        {
-            currentString.Truncate(cursor + 1);
-        }
-    }
-
-    BOOL StringLexer::IsSeparatorChar(WCHAR wcChar)
-    {
-        return ((wcChar == W(',')) || (wcChar == W('=')));
-    }
-
-    StringLexer::LEXEME_TYPE StringLexer::GetLexemeType(WCHAR wcChar)
-    {
-        switch (wcChar)
-        {
-        case W('='):
-            return LEXEME_TYPE_EQUALS;
-        case W(','):
-            return LEXEME_TYPE_COMMA;
-        case 0:
-            return LEXEME_TYPE_END_OF_STREAM;
-        default:
-            return LEXEME_TYPE_STRING;
-        }
-    }
-};
index 35587df..64de57f 100644 (file)
 
 #include "ex.h"
 
-#define GO_IF_SEEN(kAssemblyIdentityFlag)                       \
-    if ((m_dwAttributesSeen & kAssemblyIdentityFlag) != 0)      \
-    {                                                           \
-        fIsValid = FALSE;                                       \
-        goto Exit;                                              \
-    }                                                           \
-    else                                                        \
-    {                                                           \
-          m_dwAttributesSeen |= kAssemblyIdentityFlag;          \
-    }
-
-#define GO_IF_WILDCARD(valueString)             \
-    {                                           \
-        SmallStackSString wildCard(W("*"));       \
-        if (valueString.Equals(wildCard))       \
-        {                                       \
-            goto Exit;                          \
-        }                                       \
-    }
-
-#define GO_IF_VALIDATE_FAILED(validateProc, kIdentityFlag)      \
-    if (!validateProc(valueString))                             \
-    {                                                           \
-        fIsValid = FALSE;                                       \
-        goto Exit;                                              \
-    }                                                           \
-    else                                                        \
-    {                                                           \
-        m_pAssemblyIdentity->SetHave(kIdentityFlag);            \
-   }
-
-#define FROMHEX(a) ((a)>=W('a') ? a - W('a') + 10 : a - W('0'))
 #define TOHEX(a) ((a)>=10 ? W('a')+(a)-10 : W('0')+(a))
 #define TOLOWER(a) (((a) >= W('A') && (a) <= W('Z')) ? (W('a') + (a - W('A'))) : (a))
 
@@ -60,23 +28,6 @@ namespace BINDER_SPACE
         const int iVersionMax = 65535;
         const int iVersionParts = 4;
 
-        inline void UnicodeHexToBin(LPCWSTR pSrc, UINT cSrc, LPBYTE pDest)
-        {
-            BYTE v;
-            LPBYTE pd = pDest;
-            LPCWSTR ps = pSrc;
-
-            if (cSrc == 0)
-                return;
-
-            for (UINT i = 0; i < cSrc-1; i+=2)
-            {
-                v =  (BYTE)FROMHEX(TOLOWER(ps[i])) << 4;
-                v |= FROMHEX(TOLOWER(ps[i+1]));
-                *(pd++) = v;
-            }
-        }
-
         inline void BinToUnicodeHex(const BYTE *pSrc, UINT cSrc, _Out_writes_(2*cSrc) LPWSTR pDst)
         {
             UINT x;
@@ -93,50 +44,6 @@ namespace BINDER_SPACE
             }
         }
 
-        inline bool EqualsCaseInsensitive(const SString &a, LPCWSTR wzB)
-        {
-            return SString::_wcsicmp(a.GetUnicode(), wzB) == 0;
-        }
-
-        BOOL ValidateHex(SString &publicKeyOrToken)
-        {
-            if ((publicKeyOrToken.GetCount() == 0) || ((publicKeyOrToken.GetCount() % 2) != 0))
-            {
-                return FALSE;
-            }
-
-            SString::Iterator cursor = publicKeyOrToken.Begin();
-            SString::Iterator end = publicKeyOrToken.End() - 1;
-
-            while (cursor <= end)
-            {
-                WCHAR wcCurrentChar = cursor[0];
-
-                if (((wcCurrentChar >= W('0')) && (wcCurrentChar <= W('9'))) ||
-                    ((wcCurrentChar >= W('a')) && (wcCurrentChar <= W('f'))) ||
-                    ((wcCurrentChar >= W('A')) && (wcCurrentChar <= W('F'))))
-                {
-                    cursor++;
-                    continue;
-                }
-
-                return FALSE;
-            }
-
-            return TRUE;
-        }
-
-        inline BOOL ValidatePublicKeyToken(SString &publicKeyToken)
-        {
-            return ((publicKeyToken.GetCount() == (iPublicKeyTokenLength * 2)) &&
-                    ValidateHex(publicKeyToken));
-        }
-
-        inline BOOL ValidatePublicKey(SString &publicKey)
-        {
-            return ValidateHex(publicKey);
-        }
-
         const struct {
             LPCWSTR strValue;
             PEKIND enumValue;
@@ -146,21 +53,6 @@ namespace BINDER_SPACE
                                       { W("ARM"), peARM },
                                       { W("MSIL"), peMSIL } };
 
-        BOOL ValidateAndConvertProcessorArchitecture(SString &processorArchitecture,
-                                                     PEKIND *pkProcessorArchitecture)
-        {
-            for (int i = LENGTH_OF(wszKnownArchitectures); i--;)
-            {
-                if (EqualsCaseInsensitive(processorArchitecture, wszKnownArchitectures[i].strValue))
-                {
-                    *pkProcessorArchitecture = wszKnownArchitectures[i].enumValue;
-                    return TRUE;
-                }
-            }
-
-            return FALSE;
-        }
-
         LPCWSTR PeKindToString(PEKIND kProcessorArchitecture)
         {
             _ASSERTE(kProcessorArchitecture != peNone);
@@ -187,41 +79,12 @@ namespace BINDER_SPACE
 
             return NULL;
         }
-    };  // namespace (anonymous)
-
-    TextualIdentityParser::TextualIdentityParser(AssemblyIdentity *pAssemblyIdentity)
-    {
-        m_pAssemblyIdentity = pAssemblyIdentity;
-        m_dwAttributesSeen = AssemblyIdentity::IDENTITY_FLAG_EMPTY;
-    }
-
-    TextualIdentityParser::~TextualIdentityParser()
-    {
-        // Nothing to do here
-    }
-
-    /* static */
-    HRESULT TextualIdentityParser::Parse(SString          &textualIdentity,
-                                         AssemblyIdentity *pAssemblyIdentity)
-    {
-        HRESULT hr = S_OK;
 
-        IF_FALSE_GO(pAssemblyIdentity != NULL);
-
-        EX_TRY
+        BOOL IsWhitespace(WCHAR wcChar)
         {
-            TextualIdentityParser identityParser(pAssemblyIdentity);
-
-            if (!identityParser.Parse(textualIdentity))
-            {
-                IF_FAIL_GO(FUSION_E_INVALID_NAME);
-            }
+            return ((wcChar == L'\n') || (wcChar == L'\r') || (wcChar == L' ') || (wcChar == L'\t'));
         }
-        EX_CATCH_HRESULT(hr);
-
-    Exit:
-        return hr;
-    }
+    };  // namespace (anonymous)
 
     /* static */
     HRESULT TextualIdentityParser::ToString(AssemblyIdentity *pAssemblyIdentity,
@@ -322,126 +185,6 @@ namespace BINDER_SPACE
     }
 
     /* static */
-    BOOL TextualIdentityParser::ParseVersion(SString         &versionString,
-                                             AssemblyVersion *pAssemblyVersion)
-    {
-        BOOL fIsValid = FALSE;
-        DWORD dwFoundNumbers = 0;
-        bool foundUnspecifiedComponent = false;
-        const DWORD UnspecifiedNumber = (DWORD)-1;
-        DWORD dwCurrentNumber = UnspecifiedNumber;
-        DWORD dwNumbers[iVersionParts] = {UnspecifiedNumber, UnspecifiedNumber, UnspecifiedNumber, UnspecifiedNumber};
-
-        if (versionString.GetCount() > 0) {
-            SString::Iterator cursor = versionString.Begin();
-            SString::Iterator end = versionString.End();
-
-            while (cursor <= end)
-            {
-                WCHAR wcCurrentChar = cursor[0];
-
-                if (dwFoundNumbers >= static_cast<DWORD>(iVersionParts))
-                {
-                    goto Exit;
-                }
-                else if (wcCurrentChar == W('.') || wcCurrentChar == W('\0'))
-                {
-                    if (dwCurrentNumber == UnspecifiedNumber)
-                    {
-                        // Difference from .NET Framework, compat with Version(string) constructor: A missing version component
-                        // is considered invalid.
-                        //
-                        // Examples:
-                        //   "MyAssembly, Version=."
-                        //   "MyAssembly, Version=1."
-                        //   "MyAssembly, Version=.1"
-                        //   "MyAssembly, Version=1..1"
-                        goto Exit;
-                    }
-
-                    // Compat with .NET Framework: A value of iVersionMax is considered unspecified. Once an unspecified
-                    // component is found, validate the remaining components but consider them as unspecified as well.
-                    if (dwCurrentNumber == iVersionMax)
-                    {
-                        foundUnspecifiedComponent = true;
-                        dwCurrentNumber = UnspecifiedNumber;
-                    }
-                    else if (!foundUnspecifiedComponent)
-                    {
-                        dwNumbers[dwFoundNumbers] = dwCurrentNumber;
-                        dwCurrentNumber = UnspecifiedNumber;
-                    }
-
-                    dwFoundNumbers++;
-                }
-                else if ((wcCurrentChar >= W('0')) && (wcCurrentChar <= W('9')))
-                {
-                    if (dwCurrentNumber == UnspecifiedNumber)
-                    {
-                        dwCurrentNumber = 0;
-                    }
-                    dwCurrentNumber = (dwCurrentNumber * 10) + (wcCurrentChar - W('0'));
-
-                    if (dwCurrentNumber > static_cast<DWORD>(iVersionMax))
-                    {
-                        goto Exit;
-                    }
-                }
-                else
-                {
-                    goto Exit;
-                }
-
-                cursor++;
-            }
-
-            // Difference from .NET Framework: If the major or minor version are unspecified, the version is considered invalid.
-            //
-            // Examples:
-            //   "MyAssembly, Version="
-            //   "MyAssembly, Version=1"
-            //   "MyAssembly, Version=65535.1"
-            //   "MyAssembly, Version=1.65535"
-            if (dwFoundNumbers < 2 || dwNumbers[0] == UnspecifiedNumber || dwNumbers[1] == UnspecifiedNumber)
-            {
-                goto Exit;
-            }
-
-            pAssemblyVersion->SetFeatureVersion(dwNumbers[0], dwNumbers[1]);
-            pAssemblyVersion->SetServiceVersion(dwNumbers[2], dwNumbers[3]);
-            fIsValid = TRUE;
-        }
-
-    Exit:
-        return fIsValid;
-    }
-
-    /* static */
-    BOOL TextualIdentityParser::HexToBlob(SString &publicKeyOrToken,
-                                          BOOL     fValidateHex,
-                                          BOOL     fIsToken,
-                                          SBuffer &publicKeyOrTokenBLOB)
-    {
-        // Optional input verification
-        if (fValidateHex)
-        {
-            if ((fIsToken && !ValidatePublicKeyToken(publicKeyOrToken)) ||
-                (!fIsToken && !ValidatePublicKey(publicKeyOrToken)))
-            {
-                return FALSE;
-            }
-        }
-
-        UINT ccPublicKeyOrToken = publicKeyOrToken.GetCount();
-        BYTE *pByteBLOB = publicKeyOrTokenBLOB.OpenRawBuffer(ccPublicKeyOrToken / 2);
-
-        UnicodeHexToBin(publicKeyOrToken.GetUnicode(), ccPublicKeyOrToken, pByteBLOB);
-        publicKeyOrTokenBLOB.CloseRawBuffer();
-
-        return TRUE;
-    }
-
-    /* static */
     void TextualIdentityParser::BlobToHex(SBuffer &publicKeyOrTokenBLOB,
                                           SString &publicKeyOrToken)
     {
@@ -453,183 +196,6 @@ namespace BINDER_SPACE
         publicKeyOrToken.CloseBuffer(cbPublicKeyOrTokenBLOB * 2);
     }
 
-    BOOL TextualIdentityParser::Parse(SString &textualIdentity)
-    {
-        BOOL fIsValid = TRUE;
-        SString unicodeTextualIdentity;
-
-        // Lexer modifies input string
-        textualIdentity.ConvertToUnicode(unicodeTextualIdentity);
-        Init(unicodeTextualIdentity);
-
-        SmallStackSString currentString;
-
-        // Identity format is simple name (, attr = value)*
-        GO_IF_NOT_EXPECTED(GetNextLexeme(currentString), LEXEME_TYPE_STRING);
-        m_pAssemblyIdentity->m_simpleName.Set(currentString);
-        m_pAssemblyIdentity->m_simpleName.Normalize();
-        m_pAssemblyIdentity->SetHave(AssemblyIdentity::IDENTITY_FLAG_SIMPLE_NAME);
-
-        for (;;)
-        {
-            SmallStackSString attributeString;
-            SmallStackSString valueString;
-
-            GO_IF_END_OR_NOT_EXPECTED(GetNextLexeme(currentString), LEXEME_TYPE_COMMA);
-            GO_IF_NOT_EXPECTED(GetNextLexeme(attributeString), LEXEME_TYPE_STRING);
-            GO_IF_NOT_EXPECTED(GetNextLexeme(currentString), LEXEME_TYPE_EQUALS);
-            GO_IF_NOT_EXPECTED(GetNextLexeme(valueString), LEXEME_TYPE_STRING);
-
-            if (!PopulateAssemblyIdentity(attributeString, valueString))
-            {
-                fIsValid = FALSE;
-                break;
-            }
-        }
-
-    Exit:
-        return fIsValid;
-    }
-
-    BOOL TextualIdentityParser::ParseString(SString &textualString,
-                                            SString &contentString)
-    {
-        BOOL fIsValid = TRUE;
-        SString unicodeTextualString;
-
-        // Lexer modifies input string
-        textualString.ConvertToUnicode(unicodeTextualString);
-        Init(unicodeTextualString);
-
-        SmallStackSString currentString;
-        GO_IF_NOT_EXPECTED(GetNextLexeme(currentString), LEXEME_TYPE_STRING);
-
-        contentString.Set(currentString);
-        currentString.Normalize();
-
-    Exit:
-        return fIsValid;
-    }
-
-    BOOL TextualIdentityParser::PopulateAssemblyIdentity(SString &attributeString,
-                                                         SString &valueString)
-    {
-        BOOL fIsValid = TRUE;
-
-        if (EqualsCaseInsensitive(attributeString, W("culture")))
-        {
-            GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_CULTURE);
-            GO_IF_WILDCARD(valueString);
-
-            if (!EqualsCaseInsensitive(valueString, W("neutral")))
-            {
-                // culture/language is preserved as is
-                m_pAssemblyIdentity->m_cultureOrLanguage.Set(valueString);
-                m_pAssemblyIdentity->m_cultureOrLanguage.Normalize();
-            }
-
-            m_pAssemblyIdentity->SetHave(AssemblyIdentity::IDENTITY_FLAG_CULTURE);
-        }
-        else if (EqualsCaseInsensitive(attributeString, W("version")))
-        {
-            AssemblyVersion *pAssemblyVersion = &(m_pAssemblyIdentity->m_version);
-
-            GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_VERSION);
-            GO_IF_WILDCARD(valueString);
-
-            if (ParseVersion(valueString, pAssemblyVersion))
-            {
-                m_pAssemblyIdentity->SetHave(AssemblyIdentity::IDENTITY_FLAG_VERSION);
-            }
-            else
-            {
-                fIsValid = FALSE;
-            }
-        }
-        else if (EqualsCaseInsensitive(attributeString, W("publickeytoken")))
-        {
-            GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY);
-            GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN);
-            GO_IF_WILDCARD(valueString);
-
-            if (!EqualsCaseInsensitive(valueString, W("null")))
-            {
-                GO_IF_VALIDATE_FAILED(ValidatePublicKeyToken,
-                                      AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN);
-                HexToBlob(valueString,
-                          FALSE /* fValidateHex */,
-                          TRUE /* fIsToken */,
-                          m_pAssemblyIdentity->m_publicKeyOrTokenBLOB);
-            }
-            else
-            {
-                m_pAssemblyIdentity->SetHave(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN_NULL);
-            }
-        }
-        else if (EqualsCaseInsensitive(attributeString, W("publickey")))
-        {
-            GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN);
-            GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY);
-
-            if (!EqualsCaseInsensitive(valueString, W("null")))
-            {
-                GO_IF_VALIDATE_FAILED(ValidatePublicKey, AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY);
-                HexToBlob(valueString,
-                          FALSE /* fValidateHex */,
-                          FALSE /* fIsToken */,
-                          m_pAssemblyIdentity->m_publicKeyOrTokenBLOB);
-            }
-        }
-        else if (EqualsCaseInsensitive(attributeString, W("processorarchitecture")))
-        {
-            PEKIND kProcessorArchitecture = peNone;
-
-            GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_PROCESSOR_ARCHITECTURE);
-            GO_IF_WILDCARD(valueString);
-
-            if (ValidateAndConvertProcessorArchitecture(valueString, &kProcessorArchitecture))
-            {
-                m_pAssemblyIdentity->m_kProcessorArchitecture = kProcessorArchitecture;
-                m_pAssemblyIdentity->SetHave(AssemblyIdentity::IDENTITY_FLAG_PROCESSOR_ARCHITECTURE);
-            }
-            else
-            {
-                fIsValid = FALSE;
-            }
-        }
-        else if (EqualsCaseInsensitive(attributeString, W("retargetable")))
-        {
-            GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_RETARGETABLE);
-
-            if (EqualsCaseInsensitive(valueString, W("yes")))
-            {
-                m_pAssemblyIdentity->SetHave(AssemblyIdentity::IDENTITY_FLAG_RETARGETABLE);
-            }
-            else if (!EqualsCaseInsensitive(valueString, W("no")))
-            {
-                fIsValid = FALSE;
-            }
-        }
-        else if (EqualsCaseInsensitive(attributeString, W("contenttype")))
-        {
-            GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_CONTENT_TYPE);
-            GO_IF_WILDCARD(valueString);
-
-            if (EqualsCaseInsensitive(valueString, W("windowsruntime")))
-            {
-                m_pAssemblyIdentity->m_kContentType = AssemblyContentType_WindowsRuntime;
-                m_pAssemblyIdentity->SetHave(AssemblyIdentity::IDENTITY_FLAG_CONTENT_TYPE);
-            }
-            else
-            {
-                fIsValid = FALSE;
-            }
-        }
-
-    Exit:
-        return fIsValid;
-    }
-
     /* static */
     void TextualIdentityParser::EscapeString(SString &input,
                                              SString &result)
index ce2c001..a7a9733 100644 (file)
   <ItemGroup>
     <Compile Include="System\Reflection\RuntimeAssembly.cs" />
     <Compile Include="System\Reflection\RuntimeAssemblyName.cs" />
-    <Compile Include="System\Reflection\AssemblyNameHelpers.cs" />
     <Compile Include="System\Reflection\AssemblyRuntimeNameHelpers.cs" />
     <Compile Include="System\Reflection\Attribute.CoreRT.cs" />
     <Compile Include="System\Reflection\Assembly.CoreRT.cs" />
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.cs
deleted file mode 100644 (file)
index a79f9f7..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Globalization;
-using System.IO;
-using System.Text;
-using System.Collections.Generic;
-
-namespace System.Reflection
-{
-    internal static partial class AssemblyNameHelpers
-    {
-        //
-        // These helpers convert between the combined flags+contentType+processorArchitecture value and the separated parts.
-        //
-        // Since these are only for trusted callers, they do NOT check for out of bound bits.
-        //
-
-        internal static AssemblyContentType ExtractAssemblyContentType(this AssemblyNameFlags flags)
-        {
-            return (AssemblyContentType)((((int)flags) >> 9) & 0x7);
-        }
-
-        internal static AssemblyNameFlags ExtractAssemblyNameFlags(this AssemblyNameFlags combinedFlags)
-        {
-            return combinedFlags & unchecked((AssemblyNameFlags)0xFFFFF10F);
-        }
-    }
-}
index f4dbc0d..9837460 100644 (file)
@@ -142,8 +142,8 @@ namespace System.Reflection
 
             // Our "Flags" contain both the classic flags and the ProcessorArchitecture + ContentType bits. The public AssemblyName has separate properties for
             // these. The setters for these properties quietly mask out any bits intended for the other one, so we needn't do that ourselves..
-            blank.Flags = this.Flags.ExtractAssemblyNameFlags();
-            blank.ContentType = this.Flags.ExtractAssemblyContentType();
+            blank.Flags = ExtractAssemblyNameFlags(this.Flags);
+            blank.ContentType = ExtractAssemblyContentType(this.Flags);
 #pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete
             blank.ProcessorArchitecture = ExtractProcessorArchitecture(this.Flags);
 #pragma warning restore SYSLIB0037
@@ -169,13 +169,17 @@ namespace System.Reflection
             get
             {
                 byte[]? pkt = (0 != (Flags & AssemblyNameFlags.PublicKey)) ? AssemblyNameHelpers.ComputePublicKeyToken(PublicKeyOrToken) : PublicKeyOrToken;
-                return AssemblyNameFormatter.ComputeDisplayName(Name, Version, CultureName, pkt, Flags.ExtractAssemblyNameFlags(), Flags.ExtractAssemblyContentType());
+                return AssemblyNameFormatter.ComputeDisplayName(Name, Version, CultureName, pkt, ExtractAssemblyNameFlags(Flags), ExtractAssemblyContentType(Flags));
             }
         }
 
-        internal static ProcessorArchitecture ExtractProcessorArchitecture(AssemblyNameFlags flags)
-        {
-            return (ProcessorArchitecture)((((int)flags) >> 4) & 0x7);
-        }
+        private static AssemblyNameFlags ExtractAssemblyNameFlags(AssemblyNameFlags combinedFlags)
+            => combinedFlags & unchecked((AssemblyNameFlags)0xFFFFF10F);
+
+        private static AssemblyContentType ExtractAssemblyContentType(AssemblyNameFlags flags)
+            => (AssemblyContentType)((((int)flags) >> 9) & 0x7);
+
+        private static ProcessorArchitecture ExtractProcessorArchitecture(AssemblyNameFlags flags)
+            => (ProcessorArchitecture)((((int)flags) >> 4) & 0x7);
     }
 }
index a7ae99a..e02ce4b 100644 (file)
@@ -2238,9 +2238,8 @@ ReleaseHolder<FriendAssemblyDescriptor> FriendAssemblyDescriptor::CreateFriendAs
 
             // Create an AssemblyNameObject from the string.
             FriendAssemblyNameHolder pFriendAssemblyName;
-            StackScratchBuffer buffer;
             pFriendAssemblyName = new FriendAssemblyName_t;
-            hr = pFriendAssemblyName->Init(displayName.GetUTF8(buffer));
+            hr = pFriendAssemblyName->InitNoThrow(displayName);
 
             if (SUCCEEDED(hr))
             {
index b1f270e..bbff58b 100644 (file)
@@ -142,5 +142,6 @@ extern "C" void QCALLTYPE AssemblyNative_ApplyUpdate(QCall::AssemblyHandle assem
 
 extern "C" BOOL QCALLTYPE AssemblyNative_IsApplyUpdateSupported();
 
-#endif
+extern "C" void QCALLTYPE AssemblyName_InitializeAssemblySpec(NativeAssemblyNameParts* pAssemblyNameParts, BaseAssemblySpec* pAssemblySpec);
 
+#endif
index 7d25d34..fbc0afa 100644 (file)
@@ -235,26 +235,3 @@ BOOL BaseAssemblySpec::RefMatchesDef(const BaseAssemblySpec* pRef, const BaseAss
         return (CompareStrings(pRef->GetName(), pDef->GetName())==0);
     }
 }
-
-VOID BaseAssemblySpec::SetName(SString const & ssName)
-{
-    CONTRACTL
-    {
-        INSTANCE_CHECK;
-        GC_NOTRIGGER;
-        THROWS;
-    }
-    CONTRACTL_END;
-
-    if (m_ownedFlags & NAME_OWNED)
-    {
-        delete [] m_pAssemblyName;
-        m_ownedFlags &= ~NAME_OWNED;
-    }
-
-    m_pAssemblyName = NULL;
-
-    IfFailThrow(FString::ConvertUnicode_Utf8(ssName.GetUnicode(), & ((LPSTR &) m_pAssemblyName)));
-
-    m_ownedFlags |= NAME_OWNED;
-}
index ab98a4f..77180a3 100644 (file)
@@ -50,7 +50,9 @@ public:
 
     HRESULT Init(mdToken tkAssemblyRef, IMDInternalImport *pImport);
     HRESULT Init(mdAssembly tkAssemblyRef, IMetaDataAssemblyImport* pImport);
-    HRESULT Init(LPCSTR pAssemblyDisplayName);
+
+    void Init(SString& assemblyDisplayName);
+    HRESULT InitNoThrow(SString& assemblyDisplayName);
 
     // Note that this method does not clone the fields!
     VOID CopyFrom(const BaseAssemblySpec *pSpec);
@@ -72,14 +74,12 @@ public:
         return m_pBinder;
     }
 
-    HRESULT ParseName();
     DWORD Hash();
 
     LPCSTR GetName() const;
     inline void GetName(SString & ssName) const { WRAPPER_NO_CONTRACT; ssName.SetUTF8(GetName()); }
 
     void SetName(LPCSTR szName);
-    void SetName(SString const & ssName);
 
     VOID SetCulture(LPCSTR szCulture);
 
index 97eead9..1d79bf5 100644 (file)
@@ -64,14 +64,6 @@ inline void BaseAssemblySpec::Init(LPCSTR pAssemblyName,
     m_context = *pContext;
 }
 
-inline HRESULT BaseAssemblySpec::Init(LPCSTR pAssemblyDisplayName)
-{
-    WRAPPER_NO_CONTRACT;
-    m_pAssemblyName = pAssemblyDisplayName;
-    // We eagerly parse the name to allow FusionBind::Hash to avoid throwing.
-    return ParseName();
-}
-
 inline VOID BaseAssemblySpec::CloneFields()
 {
     CONTRACTL
index b9b2d70..3b8d0c0 100644 (file)
@@ -21,7 +21,6 @@
 #include "strongnameinternal.h"
 #include "strongnameholders.h"
 
-#include "../binder/inc/textualidentityparser.hpp"
 #include "../binder/inc/assemblyidentity.hpp"
 #include "../binder/inc/assembly.hpp"
 #include "../binder/inc/assemblyname.hpp"
@@ -157,59 +156,75 @@ ErrExit:
     return hr;
 }
 
-HRESULT BaseAssemblySpec::ParseName()
+void BaseAssemblySpec::Init(SString& assemblyDisplayName)
 {
     CONTRACTL
     {
         INSTANCE_CHECK;
         GC_TRIGGERS;
-        NOTHROW;
-        INJECT_FAULT(return E_OUTOFMEMORY;);
+        THROWS;
     }
     CONTRACTL_END;
 
-    if (!m_pAssemblyName)
-        return S_OK;
+    PCWSTR pAssemblyDisplayName = assemblyDisplayName.GetUnicode();
 
-    HRESULT hr = S_OK;
+    GCX_COOP();
 
-    EX_TRY
-    {
-        BINDER_SPACE::AssemblyIdentityUTF8* pAssemblyIdentity;
-        AppDomain *pDomain = ::GetAppDomain();
-        _ASSERTE(pDomain);
+    OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
 
-        BINDER_SPACE::ApplicationContext *pAppContext = NULL;
-        DefaultAssemblyBinder *pBinder = pDomain->GetDefaultBinder();
+    PREPARE_NONVIRTUAL_CALLSITE(METHOD__ASSEMBLY_NAME__PARSE_AS_ASSEMBLYSPEC);
+    DECLARE_ARGHOLDER_ARRAY(args, 2);
+    args[ARGNUM_0] = PTR_TO_ARGHOLDER(pAssemblyDisplayName);
+    args[ARGNUM_1] = PTR_TO_ARGHOLDER(this);
+    CALL_MANAGED_METHOD_NORET(args);
+}
 
-        hr = pBinder->GetAppContext()->GetAssemblyIdentity(m_pAssemblyName, &pAssemblyIdentity);
+extern "C" void QCALLTYPE AssemblyName_InitializeAssemblySpec(NativeAssemblyNameParts* pAssemblyNameParts, BaseAssemblySpec* pAssemblySpec)
+{
+    QCALL_CONTRACT;
 
-        if (FAILED(hr))
-        {
-            m_ownedFlags |= BAD_NAME_OWNED;
-            IfFailThrow(hr);
-        }
+    BEGIN_QCALL;
 
-        // Name - does not copy the data
-        SetName(pAssemblyIdentity->GetSimpleNameUTF8());
+    StackSString ssName;
+    SString(SString::Literal, pAssemblyNameParts->_pName).ConvertToUTF8(ssName);
 
-        // Culture - does not copy the data
-        if (pAssemblyIdentity->Have(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_CULTURE))
-        {
-            if (!pAssemblyIdentity->m_cultureOrLanguage.IsEmpty())
-            {
-                SetCulture(pAssemblyIdentity->GetCultureOrLanguageUTF8());
-            }
-            else
-            {
-                SetCulture("");
-            }
-        }
+    AssemblyMetaDataInternal asmInfo;
+
+    asmInfo.usMajorVersion = pAssemblyNameParts->_major;
+    asmInfo.usMinorVersion = pAssemblyNameParts->_minor;
+    asmInfo.usBuildNumber = pAssemblyNameParts->_build;
+    asmInfo.usRevisionNumber = pAssemblyNameParts->_revision;
 
-        InitializeWithAssemblyIdentity(pAssemblyIdentity);
+    SmallStackSString ssLocale;
+    if (pAssemblyNameParts->_pCultureName != NULL)
+        SString(SString::Literal, pAssemblyNameParts->_pCultureName).ConvertToUTF8(ssLocale);
+    asmInfo.szLocale = (pAssemblyNameParts->_pCultureName != NULL) ? ssLocale.GetUTF8NoConvert() : NULL;
 
-        // Copy and own any fields we do not already own
-        CloneFields();
+    // Initialize spec
+    pAssemblySpec->Init(ssName.GetUTF8NoConvert(), &asmInfo,
+        pAssemblyNameParts->_pPublicKeyOrToken, pAssemblyNameParts->_cbPublicKeyOrToken, pAssemblyNameParts->_flags);
+
+    // Copy and own any fields we do not own
+    pAssemblySpec->CloneFields();
+
+    END_QCALL;
+}
+
+HRESULT BaseAssemblySpec::InitNoThrow(SString& assemblyDisplayName)
+{
+    CONTRACTL
+    {
+        INSTANCE_CHECK;
+        GC_TRIGGERS;
+        NOTHROW;
+    }
+    CONTRACTL_END;
+
+    HRESULT hr = S_OK;
+
+    EX_TRY
+    {
+        Init(assemblyDisplayName);
     }
     EX_CATCH_HRESULT(hr);
 
@@ -417,8 +432,8 @@ VOID BaseAssemblySpec::GetDisplayName(DWORD flags, SString &result) const
     }
 
     IfFailThrow(BINDER_SPACE::TextualIdentityParser::ToString(&assemblyIdentity,
-                                                              assemblyIdentity.m_dwIdentityFlags,
-                                                              result));
+                                                             assemblyIdentity.m_dwIdentityFlags,
+                                                             result));
 }
 
 void BaseAssemblySpec::PopulateAssemblyNameData(AssemblyNameData &data) const
index c9c5a7b..5ad8c85 100644 (file)
@@ -115,6 +115,7 @@ DEFINE_FIELD(ARRAY_WITH_OFFSET,     M_COUNT,                m_count)
 
 DEFINE_CLASS(ASSEMBLY_NAME,         Reflection,             AssemblyName)
 DEFINE_METHOD(ASSEMBLY_NAME,        CTOR,                   .ctor,                     IM_PtrNativeAssemblyNameParts)
+DEFINE_METHOD(ASSEMBLY_NAME,        PARSE_AS_ASSEMBLYSPEC,  ParseAsAssemblySpec,       SM_PtrCharPtrVoid)
 
 DEFINE_CLASS(NATIVE_ASSEMBLY_NAME_PARTS,   Reflection,             NativeAssemblyNameParts)
 // ASSEMBLYBASE is System.ReflectionAssembly while ASSEMBLY is System.Reflection.RuntimeAssembly
index efb3565..68b2603 100644 (file)
@@ -740,7 +740,6 @@ HRESULT CorHost2::CreateDelegate(
     BEGIN_EXTERNAL_ENTRYPOINT(&hr);
     GCX_COOP_THREAD_EXISTS(GET_THREAD());
 
-    MAKE_UTF8PTR_FROMWIDE(szAssemblyName, wszAssemblyName);
     MAKE_UTF8PTR_FROMWIDE(szClassName, wszClassName);
     MAKE_UTF8PTR_FROMWIDE(szMethodName, wszMethodName);
 
@@ -748,7 +747,8 @@ HRESULT CorHost2::CreateDelegate(
         GCX_PREEMP();
 
         AssemblySpec spec;
-        spec.Init(szAssemblyName);
+        SString ssAssemblyName(wszAssemblyName);
+        spec.Init(ssAssemblyName);
         Assembly* pAsm=spec.LoadAssembly(FILE_ACTIVE);
 
         TypeHandle th=pAsm->GetLoader()->LoadTypeByNameThrowing(pAsm,NULL,szClassName);
index 403952c..d6f082a 100644 (file)
@@ -385,6 +385,7 @@ DEFINE_METASIG_T(IM(RetAssemblyName, _, C(ASSEMBLY_NAME)))
 DEFINE_METASIG_T(IM(RetAssemblyBase, _, C(ASSEMBLYBASE)))
 DEFINE_METASIG_T(IM(RetModule, _, C(MODULE)))
 DEFINE_METASIG_T(IM(PtrNativeAssemblyNameParts, P(g(NATIVE_ASSEMBLY_NAME_PARTS)), v))
+DEFINE_METASIG(SM(PtrCharPtrVoid, P(u) P(v), v))
 DEFINE_METASIG(IM(RetObj, _, j))
 DEFINE_METASIG(SM(RetObj, _, j))
 DEFINE_METASIG_T(IM(RetIEnumerator, _, C(IENUMERATOR)))
index 7e65ecb..c651202 100644 (file)
@@ -825,14 +825,10 @@ DomainAssembly * MulticoreJitProfilePlayer::LoadAssembly(SString & assemblyName)
 {
     STANDARD_VM_CONTRACT;
 
-    // Get the assembly name.
-    StackScratchBuffer scratch;
-    const ANSI* pAnsiAssemblyName = assemblyName.GetANSI(scratch);
-
     AssemblySpec spec;
 
     // Initialize the assembly spec.
-    HRESULT hr = spec.Init(pAnsiAssemblyName);
+    HRESULT hr = spec.InitNoThrow(assemblyName);
     if (FAILED(hr))
     {
         return NULL;
index fbefbfe..891ce48 100644 (file)
@@ -700,7 +700,8 @@ namespace
             while (COMCharacter::nativeIsWhiteSpace(*(++szComma)));
 
             AssemblySpec spec;
-            if (SUCCEEDED(spec.Init(szComma)))
+            SString ssAssemblyDisplayName(SString::Utf8, szComma);
+            if (SUCCEEDED(spec.InitNoThrow(ssAssemblyDisplayName)))
             {
                 // Need to perform case insensitive hashing.
                 SString moduleName(SString::Utf8, szLibName);
index d47454b..d2e3a55 100644 (file)
@@ -158,6 +158,7 @@ static const Entry s_QCall[] =
     DllImportEntry(TypeName_GetTypeArguments)
     DllImportEntry(TypeName_GetModifiers)
     DllImportEntry(TypeName_GetAssemblyName)
+    DllImportEntry(AssemblyName_InitializeAssemblySpec)
     DllImportEntry(AssemblyNative_GetFullName)
     DllImportEntry(AssemblyNative_GetLocation)
     DllImportEntry(AssemblyNative_GetResource)
index dab28d4..f5e1a97 100644 (file)
@@ -1397,18 +1397,18 @@ DomainAssembly * LoadDomainAssembly(
 {
     CONTRACTL
     {
-        MODE_ANY;
+        MODE_COOPERATIVE;
         THROWS;
         GC_TRIGGERS;
         INJECT_FAULT(COMPlusThrowOM(););
     }
     CONTRACTL_END;
+
     AssemblySpec spec;
     DomainAssembly *pDomainAssembly = NULL;
 
-    StackScratchBuffer buffer;
-    LPCUTF8 szAssemblySpec = psszAssemblySpec ? psszAssemblySpec->GetUTF8(buffer) : NULL;
-    IfFailThrow(spec.Init(szAssemblySpec));
+    StackSString ssAssemblyName(*psszAssemblySpec);
+    spec.Init(ssAssemblyName);
 
     if (pRequestingAssembly)
     {
index e80755d..05cbc2a 100644 (file)
@@ -2,6 +2,8 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
 using System.Runtime.CompilerServices;
 using System.Text;
 
@@ -12,7 +14,7 @@ namespace System.Reflection
     //
     internal ref struct AssemblyNameParser
     {
-        public struct AssemblyNameParts
+        public readonly struct AssemblyNameParts
         {
             public AssemblyNameParts(string name, Version? version, string? cultureName, AssemblyNameFlags flags, byte[]? publicKeyOrToken)
             {
@@ -23,11 +25,11 @@ namespace System.Reflection
                 _publicKeyOrToken = publicKeyOrToken;
             }
 
-            public string _name;
-            public Version? _version;
-            public string? _cultureName;
-            public AssemblyNameFlags _flags;
-            public byte[]? _publicKeyOrToken;
+            public readonly string _name;
+            public readonly Version? _version;
+            public readonly string? _cultureName;
+            public readonly AssemblyNameFlags _flags;
+            public readonly byte[]? _publicKeyOrToken;
         }
 
         // Token categories for the lexer.
@@ -50,12 +52,11 @@ namespace System.Reflection
         }
 
         private static readonly char[] s_illegalCharactersInSimpleName = { '/', '\\', ':' };
-        private string _input;
+        private ReadOnlySpan<char> _input;
         private int _index;
 
-        private AssemblyNameParser(string input)
+        private AssemblyNameParser(ReadOnlySpan<char> input)
         {
-            Debug.Assert(input != null);
             if (input.Length == 0)
                 throw new ArgumentException(SR.Format_StringZeroLength);
 
@@ -63,33 +64,34 @@ namespace System.Reflection
             _index = 0;
         }
 
-        public static AssemblyNameParts Parse(string s)
+        public static AssemblyNameParts Parse(string name)
         {
-            return new AssemblyNameParser(s).Parse();
+            return new AssemblyNameParser(name).Parse();
+        }
+
+        public static AssemblyNameParts Parse(ReadOnlySpan<char> name)
+        {
+            return new AssemblyNameParser(name).Parse();
         }
 
         private void RecordNewSeenOrThrow(ref AttributeKind seenAttributes, AttributeKind newAttribute)
         {
             if ((seenAttributes & newAttribute) != 0)
             {
-                ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
-            }
-            else
-            {
-                seenAttributes |= newAttribute;
+                ThrowInvalidAssemblyName();
             }
+            seenAttributes |= newAttribute;
         }
 
         private AssemblyNameParts Parse()
         {
             // Name must come first.
-            string name;
-            Token token = GetNextToken(out name);
+            Token token = GetNextToken(out string name);
             if (token != Token.String)
-                ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+                ThrowInvalidAssemblyName();
 
             if (name == string.Empty || name.IndexOfAny(s_illegalCharactersInSimpleName) != -1)
-                ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+                ThrowInvalidAssemblyName();
 
             Version? version = null;
             string? cultureName = null;
@@ -101,23 +103,22 @@ namespace System.Reflection
             while (token != Token.End)
             {
                 if (token != Token.Comma)
-                    ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
-                string attributeName;
+                    ThrowInvalidAssemblyName();
 
-                token = GetNextToken(out attributeName);
+                token = GetNextToken(out string attributeName);
                 if (token != Token.String)
-                    ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
-                token = GetNextToken();
+                    ThrowInvalidAssemblyName();
 
+                token = GetNextToken();
                 if (token != Token.Equals)
-                    ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
-                string attributeValue;
-                token = GetNextToken(out attributeValue);
+                    ThrowInvalidAssemblyName();
+
+                token = GetNextToken(out string attributeValue);
                 if (token != Token.String)
-                    ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+                    ThrowInvalidAssemblyName();
 
                 if (attributeName == string.Empty)
-                    ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+                    ThrowInvalidAssemblyName();
 
                 if (attributeName.Equals("Version", StringComparison.OrdinalIgnoreCase))
                 {
@@ -154,22 +155,30 @@ namespace System.Reflection
                 {
                     RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.Retargetable);
                     if (attributeValue.Equals("Yes", StringComparison.OrdinalIgnoreCase))
+                    {
                         flags |= AssemblyNameFlags.Retargetable;
+                    }
                     else if (attributeValue.Equals("No", StringComparison.OrdinalIgnoreCase))
                     {
                         // nothing to do
                     }
                     else
-                        ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+                    {
+                        ThrowInvalidAssemblyName();
+                    }
                 }
 
                 if (attributeName.Equals("ContentType", StringComparison.OrdinalIgnoreCase))
                 {
                     RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.ContentType);
                     if (attributeValue.Equals("WindowsRuntime", StringComparison.OrdinalIgnoreCase))
+                    {
                         flags |= (AssemblyNameFlags)(((int)AssemblyContentType.WindowsRuntime) << 9);
+                    }
                     else
-                        ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+                    {
+                        ThrowInvalidAssemblyName();
+                    }
                 }
 
                 // Desktop compat: If we got here, the attribute name is unknown to us. Ignore it.
@@ -183,8 +192,8 @@ namespace System.Reflection
         {
             string[] parts = attributeValue.Split('.');
             if (parts.Length > 4)
-                ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
-            ushort[] versionNumbers = new ushort[4];
+                ThrowInvalidAssemblyName();
+            Span<ushort> versionNumbers = stackalloc ushort[4];
             for (int i = 0; i < versionNumbers.Length; i++)
             {
                 if (i >= parts.Length)
@@ -195,17 +204,17 @@ namespace System.Reflection
                     for (int j = 0; j < parts[i].Length; j++)
                     {
                         if (!char.IsDigit(parts[i][j]))
-                            ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+                            ThrowInvalidAssemblyName();
                     }
                     if (!(ushort.TryParse(parts[i], out versionNumbers[i])))
                     {
-                        ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+                        ThrowInvalidAssemblyName();
                     }
                 }
             }
 
             if (versionNumbers[0] == ushort.MaxValue || versionNumbers[1] == ushort.MaxValue)
-                ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+                ThrowInvalidAssemblyName();
             if (versionNumbers[2] == ushort.MaxValue)
                 return new Version(versionNumbers[0], versionNumbers[1]);
             if (versionNumbers[3] == ushort.MaxValue)
@@ -229,7 +238,7 @@ namespace System.Reflection
                 return Array.Empty<byte>();
 
             if (isToken && attributeValue.Length != 8 * 2)
-                ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+                ThrowInvalidAssemblyName();
 
             byte[] pkt = new byte[attributeValue.Length / 2];
             int srcIndex = 0;
@@ -254,7 +263,7 @@ namespace System.Reflection
                 return ProcessorArchitecture.Amd64;
             if (attributeValue.Equals("arm", StringComparison.OrdinalIgnoreCase))
                 return ProcessorArchitecture.Arm;
-            ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+            ThrowInvalidAssemblyName();
             return default; // unreachable
         }
 
@@ -266,7 +275,7 @@ namespace System.Reflection
                 return (byte)(c - 'a' + 10);
             if (c >= 'A' && c <= 'F')
                 return (byte)(c - 'A' + 10);
-            ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+            ThrowInvalidAssemblyName();
             return default; // unreachable
         }
 
@@ -302,7 +311,7 @@ namespace System.Reflection
                 ch = _input[_index++];
                 if (ch == '\0')
                 {
-                    ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+                    ThrowInvalidAssemblyName();
                 }
             }
             else
@@ -357,13 +366,10 @@ namespace System.Reflection
                     if (quoteChar != 0)
                     {
                         // EOS and unclosed quotes is an error
-                        ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
-                    }
-                    else
-                    {
-                        // Reached end of input and therefore of string
-                        break;
+                        ThrowInvalidAssemblyName();
                     }
+                    // Reached end of input and therefore of string
+                    break;
                 }
 
                 if (quoteChar != 0 && c == quoteChar)
@@ -376,7 +382,7 @@ namespace System.Reflection
                 }
 
                 if (quoteChar == 0 && (c == '\'' || c == '\"'))
-                    ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+                    ThrowInvalidAssemblyName();
 
                 if (c == '\\')
                 {
@@ -401,8 +407,8 @@ namespace System.Reflection
                             sb.Append('\n');
                             break;
                         default:
-                            ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
-                            return default; //unreachable
+                            ThrowInvalidAssemblyName();
+                            break; //unreachable
                     }
                 }
                 else
@@ -423,5 +429,9 @@ namespace System.Reflection
             tokenString = sb.ToString();
             return Token.String;
         }
+
+        [DoesNotReturn]
+        private void ThrowInvalidAssemblyName()
+            => throw new FileLoadException(SR.InvalidAssemblyName, _input.ToString());
     }
 }
index b02de08..f85a121 100644 (file)
@@ -509,12 +509,6 @@ namespace System
         }
 
         [DoesNotReturn]
-        internal static void ThrowFileLoadException_InvalidAssemblyName(string name)
-        {
-            throw new FileLoadException(SR.InvalidAssemblyName, name);
-        }
-
-        [DoesNotReturn]
         internal static void ThrowArgumentOutOfRangeException_PrecisionTooLarge()
         {
             throw new ArgumentOutOfRangeException("precision", SR.Format(SR.Argument_PrecisionTooLarge, StandardFormat.MaxPrecision));