<commit_before>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.IO;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace System.Reflection.TypeLoading
{
    internal static class Helpers
    {
        public static T[] CloneArray<T>(this T[] original)
        {
            if (original == null)
                return null;

            if (original.Length == 0)
                return Array.Empty<T>();

            // We want to return the exact type of T[] even if "original" is a type of T2[] (due to array variance.)
            // The arrays produced by this helper are usually passed directly to app code.
            T[] copy = new T[original.Length];
            Array.Copy(sourceArray: original, destinationArray: copy, length: original.Length);
            return copy;
        }

        public static ReadOnlyCollection<T> ToReadOnlyCollection<T>(this IEnumerable<T> enumeration)
        {
            return new ReadOnlyCollection<T>(enumeration.ToArray());
        }

        public static int GetTokenRowNumber(this int token) => token & 0x00ffffff;

        public static RoMethod FilterInheritedAccessor(this RoMethod accessor)
        {
            if (accessor.ReflectedType == accessor.DeclaringType)
                return accessor;

            if (accessor.IsPrivate)
                return null;

            // If the accessor is virtual, NETFX tries to look for a overriding member starting from ReflectedType - a situation
            // which probably isn't expressible in any known language. Detecting overrides veers into vtable-building business which
            // is something this library tries to avoid. If anyone ever cares about this, welcome to fix. 

            return accessor;
        }

        public static MethodInfo FilterAccessor(this MethodInfo accessor, bool nonPublic)
        {
            if (nonPublic)
                return accessor;
            if (accessor.IsPublic)
                return accessor;
            return null;
        }

        public static string ComputeArraySuffix(int rank, bool multiDim)
        {
            Debug.Assert(rank == 1 || multiDim);

            if (!multiDim)
                return "[]";
            if (rank == 1)
                return "[*]";
            return "[" + new string(',', rank - 1) + "]";
        }

        // Escape identifiers as described in "Specifying Fully Qualified Type Names" on msdn.
        // Current link is http://msdn.microsoft.com/en-us/library/yfsftwz6(v=vs.110).aspx
        public static string EscapeTypeNameIdentifier(this string identifier)
        {
            // Some characters in a type name need to be escaped
            if (identifier.IndexOfAny(s_charsToEscape) != -1)
            {
                StringBuilder sbEscapedName = new StringBuilder(identifier.Length);
                foreach (char c in identifier)
                {
                    if (c.NeedsEscapingInTypeName())
                        sbEscapedName.Append('\\');

                    sbEscapedName.Append(c);
                }
                identifier = sbEscapedName.ToString();
            }
            return identifier;
        }

        public static bool TypeNameContainsTypeParserMetacharacters(this string identifier)
        {
            return identifier.IndexOfAny(s_charsToEscape) != -1;
        }

        public static bool NeedsEscapingInTypeName(this char c)
        {
            return Array.IndexOf(s_charsToEscape, c) >= 0;
        }

        private static readonly char[] s_charsToEscape = new char[] { '\\', '[', ']', '+', '*', '&', ',' };

        /// <summary>
        /// For AssemblyReferences, convert "unspecified" components from the ECMA format (0xffff) to the in-memory System.Version format (0xffffffff).
        /// </summary>
        public static Version AdjustForUnspecifiedVersionComponents(this Version v)
        {
            int mask =
                ((v.Revision == ushort.MaxValue) ? 0b0001 : 0) |
                ((v.Build == ushort.MaxValue) ? 0b0010 : 0) |
                ((v.Minor == ushort.MaxValue) ? 0b0100 : 0) |
                ((v.Major == ushort.MaxValue) ? 0b1000 : 0);

            switch (mask)
            {
                case 0b0000: return v;
                case 0b0001: return new Version(v.Major, v.Minor, v.Build);
                case 0b0010: return new Version(v.Major, v.Minor);
                case 0b0011: return new Version(v.Major, v.Minor);
                default:
                    return null;
            }
        }

        public static byte[] ComputePublicKeyToken(this byte[] pkt)
        {
            // @TODO - This is not the best way to compute the PKT as AssemblyName throws if the PK isn't a valid PK blob.
            // That's not something we should block a metadata inspection tool for so we should compute the PKT ourselves as soon as
            // we can convince the CoreFx analyzers to let us use SHA1.
            AssemblyName an = new AssemblyName();
            an.SetPublicKey(pkt);
            return an.GetPublicKeyToken();
        }

        //
        // Note that for a top level type, the resulting ns is string.Empty, *not* null.
        // This is a concession to the fact that MetadataReader's fast String equal methods
        // don't accept null.
        //
        public static void SplitTypeName(this string fullName, out string ns, out string name)
        {
            Debug.Assert(fullName != null);

            int indexOfLastDot = fullName.LastIndexOf('.');<commit_msg>Add another issue # to a todo comment. (#2448)<commit_after>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.IO;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace System.Reflection.TypeLoading
{
    internal static class Helpers
    {
        public static T[] CloneArray<T>(this T[] original)
        {
            if (original == null)
                return null;

            if (original.Length == 0)
                return Array.Empty<T>();

            // We want to return the exact type of T[] even if "original" is a type of T2[] (due to array variance.)
            // The arrays produced by this helper are usually passed directly to app code.
            T[] copy = new T[original.Length];
            Array.Copy(sourceArray: original, destinationArray: copy, length: original.Length);
            return copy;
        }

        public static ReadOnlyCollection<T> ToReadOnlyCollection<T>(this IEnumerable<T> enumeration)
        {
            return new ReadOnlyCollection<T>(enumeration.ToArray());
        }

        public static int GetTokenRowNumber(this int token) => token & 0x00ffffff;

        public static RoMethod FilterInheritedAccessor(this RoMethod accessor)
        {
            if (accessor.ReflectedType == accessor.DeclaringType)
                return accessor;

            if (accessor.IsPrivate)
                return null;

            // If the accessor is virtual, NETFX tries to look for a overriding member starting from ReflectedType - a situation
            // which probably isn't expressible in any known language. Detecting overrides veers into vtable-building business which
            // is something this library tries to avoid. If anyone ever cares about this, welcome to fix. 

            return accessor;
        }

        public static MethodInfo FilterAccessor(this MethodInfo accessor, bool nonPublic)
        {
            if (nonPublic)
                return accessor;
            if (accessor.IsPublic)
                return accessor;
            return null;
        }

        public static string ComputeArraySuffix(int rank, bool multiDim)
        {
            Debug.Assert(rank == 1 || multiDim);

            if (!multiDim)
                return "[]";
            if (rank == 1)
                return "[*]";
            return "[" + new string(',', rank - 1) + "]";
        }

        // Escape identifiers as described in "Specifying Fully Qualified Type Names" on msdn.
        // Current link is http://msdn.microsoft.com/en-us/library/yfsftwz6(v=vs.110).aspx
        public static string EscapeTypeNameIdentifier(this string identifier)
        {
            // Some characters in a type name need to be escaped
            if (identifier.IndexOfAny(s_charsToEscape) != -1)
            {
                StringBuilder sbEscapedName = new StringBuilder(identifier.Length);
                foreach (char c in identifier)
                {
                    if (c.NeedsEscapingInTypeName())
                        sbEscapedName.Append('\\');

                    sbEscapedName.Append(c);
                }
                identifier = sbEscapedName.ToString();
            }
            return identifier;
        }

        public static bool TypeNameContainsTypeParserMetacharacters(this string identifier)
        {
            return identifier.IndexOfAny(s_charsToEscape) != -1;
        }

        public static bool NeedsEscapingInTypeName(this char c)
        {
            return Array.IndexOf(s_charsToEscape, c) >= 0;
        }

        private static readonly char[] s_charsToEscape = new char[] { '\\', '[', ']', '+', '*', '&', ',' };

        /// <summary>
        /// For AssemblyReferences, convert "unspecified" components from the ECMA format (0xffff) to the in-memory System.Version format (0xffffffff).
        /// </summary>
        public static Version AdjustForUnspecifiedVersionComponents(this Version v)
        {
            int mask =
                ((v.Revision == ushort.MaxValue) ? 0b0001 : 0) |
                ((v.Build == ushort.MaxValue) ? 0b0010 : 0) |
                ((v.Minor == ushort.MaxValue) ? 0b0100 : 0) |
                ((v.Major == ushort.MaxValue) ? 0b1000 : 0);

            switch (mask)
            {
                case 0b0000: return v;
                case 0b0001: return new Version(v.Major, v.Minor, v.Build);
                case 0b0010: return new Version(v.Major, v.Minor);
                case 0b0011: return new Version(v.Major, v.Minor);
                default:
                    return null;
            }
        }

        public static byte[] ComputePublicKeyToken(this byte[] pkt)
        {
            // @TODO - https://github.com/dotnet/corefxlab/issues/2447 - This is not the best way to compute the PKT as AssemblyName
            // throws if the PK isn't a valid PK blob. That's not something we should block a metadata inspection tool for so we
            // should compute the PKT ourselves as soon as we can convince the CoreFx analyzers to let us use SHA1.
            AssemblyName an = new AssemblyName();
            an.SetPublicKey(pkt);
            return an.GetPublicKeyToken();
        }

        //
        // Note that for a top level type, the resulting ns is string.Empty, *not* null.
        // This is a concession to the fact that MetadataReader's fast String equal methods
        // don't accept null.
        //
        public static void SplitTypeName(this string fullName, out string ns, out string name)
        {
            Debug.Assert(fullName != null);

            int indexOfLastDot = fullName.LastIndexOf('.');
{'fraction_non_alphanumeric': 0.08788945154922324, 'fraction_numerical': 0.011329499613767058, 'mean_word_length': 1.847507331378299, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 23, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6276382', 'n_tokens_mistral': 3164, 'n_tokens_neox': 2913, 'n_words': 1005}