diff --git a/src/Build/Evaluation/IntrinsicFunctions.cs b/src/Build/Evaluation/IntrinsicFunctions.cs index 28e8fe62c93..3fff5c28e65 100644 --- a/src/Build/Evaluation/IntrinsicFunctions.cs +++ b/src/Build/Evaluation/IntrinsicFunctions.cs @@ -14,7 +14,6 @@ using Microsoft.Build.Shared; using Microsoft.Build.Shared.FileSystem; using Microsoft.Build.Utilities; -using Microsoft.NET.StringTools; using Microsoft.Win32; // Needed for DoesTaskHostExistForParameters @@ -399,11 +398,11 @@ internal static string ConvertFromBase64(string toDecode) } /// - /// Hash the string independent of bitness, target framework and default codepage of the environment. + /// Hash the string independent of bitness and target framework. /// internal static int StableStringHash(string toHash) { - return FowlerNollVo1aHash.ComputeHash32(toHash); + return CommunicationsUtilities.GetHashCode(toHash); } /// diff --git a/src/Build/Logging/BinaryLogger/BuildEventArgsWriter.cs b/src/Build/Logging/BinaryLogger/BuildEventArgsWriter.cs index 701c7b6b5fc..0a21182e83c 100644 --- a/src/Build/Logging/BinaryLogger/BuildEventArgsWriter.cs +++ b/src/Build/Logging/BinaryLogger/BuildEventArgsWriter.cs @@ -14,8 +14,6 @@ using Microsoft.Build.Framework; using Microsoft.Build.Framework.Profiler; using Microsoft.Build.Shared; -using Microsoft.Build.Utilities; -using Microsoft.NET.StringTools; #nullable disable @@ -1261,9 +1259,9 @@ private void Write(IExtendedBuildEventArgs extendedData) internal readonly struct HashKey : IEquatable { - private readonly long value; + private readonly ulong value; - private HashKey(long i) + private HashKey(ulong i) { value = i; } @@ -1276,13 +1274,13 @@ public HashKey(string text) } else { - value = FowlerNollVo1aHash.ComputeHash64Fast(text); + value = FnvHash64.GetHashCode(text); } } public static HashKey Combine(HashKey left, HashKey right) { - return new HashKey(FowlerNollVo1aHash.Combine64(left.value, right.value)); + return new HashKey(FnvHash64.Combine(left.value, right.value)); } public HashKey Add(HashKey other) => Combine(this, other); @@ -1312,5 +1310,35 @@ public override string ToString() return value.ToString(); } } + + internal static class FnvHash64 + { + public const ulong Offset = 14695981039346656037; + public const ulong Prime = 1099511628211; + + public static ulong GetHashCode(string text) + { + ulong hash = Offset; + + unchecked + { + for (int i = 0; i < text.Length; i++) + { + char ch = text[i]; + hash = (hash ^ ch) * Prime; + } + } + + return hash; + } + + public static ulong Combine(ulong left, ulong right) + { + unchecked + { + return (left ^ right) * Prime; + } + } + } } } diff --git a/src/StringTools/FowlerNollVo1aHash.cs b/src/StringTools/FowlerNollVo1aHash.cs deleted file mode 100644 index 7532a688669..00000000000 --- a/src/StringTools/FowlerNollVo1aHash.cs +++ /dev/null @@ -1,135 +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.Runtime.InteropServices; -using System; - -namespace Microsoft.NET.StringTools -{ - /// - /// Fowler/Noll/Vo hashing. - /// - public static class FowlerNollVo1aHash - { - // Fowler/Noll/Vo hashing. - // http://www.isthe.com/chongo/tech/comp/fnv/ - // https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash - // http://www.isthe.com/chongo/src/fnv/hash_32a.c - - // 32 bit FNV prime and offset basis for FNV-1a. - private const uint fnvPrimeA32Bit = 16777619; - private const uint fnvOffsetBasisA32Bit = 2166136261; - - // 64 bit FNV prime and offset basis for FNV-1a. - private const long fnvPrimeA64Bit = 1099511628211; - private const long fnvOffsetBasisA64Bit = unchecked((long)14695981039346656037); - - /// - /// Computes 32 bit Fowler/Noll/Vo-1a hash of a string (regardless of encoding). - /// - /// String to be hashed. - /// 32 bit signed hash - public static int ComputeHash32(string text) - { - uint hash = fnvOffsetBasisA32Bit; - -#if NET35 - unchecked - { - for (int i = 0; i < text.Length; i++) - { - char ch = text[i]; - byte b = (byte)ch; - hash ^= b; - hash *= fnvPrimeA32Bit; - - b = (byte)(ch >> 8); - hash ^= b; - hash *= fnvPrimeA32Bit; - } - } -#else - ReadOnlySpan span = MemoryMarshal.Cast(text.AsSpan()); - foreach (byte b in span) - { - hash = unchecked((hash ^ b) * fnvPrimeA32Bit); - } -#endif - - return unchecked((int)hash); - } - - /// - /// Computes 64 bit Fowler/Noll/Vo-1a hash optimized for ASCII strings. - /// The hashing algorithm considers only the first 8 bits of each character. - /// Analysis: https://github.com/KirillOsenkov/MSBuildStructuredLog/wiki/String-Hashing#faster-fnv-1a - /// - /// String to be hashed. - /// 64 bit unsigned hash - public static long ComputeHash64Fast(string text) - { - long hash = fnvOffsetBasisA64Bit; - - unchecked - { - for (int i = 0; i < text.Length; i++) - { - char ch = text[i]; - - hash = (hash ^ ch) * fnvPrimeA64Bit; - } - } - - return hash; - } - - /// - /// Computes 64 bit Fowler/Noll/Vo-1a hash of a string (regardless of encoding). - /// - /// String to be hashed. - /// 64 bit unsigned hash - public static long ComputeHash64(string text) - { - long hash = fnvOffsetBasisA64Bit; - -#if NET35 - unchecked - { - for (int i = 0; i < text.Length; i++) - { - char ch = text[i]; - byte b = (byte)ch; - hash ^= b; - hash *= fnvPrimeA64Bit; - - b = (byte)(ch >> 8); - hash ^= b; - hash *= fnvPrimeA64Bit; - } - } -#else - ReadOnlySpan span = MemoryMarshal.Cast(text.AsSpan()); - foreach (byte b in span) - { - hash = unchecked((hash ^ b) * fnvPrimeA64Bit); - } -#endif - - return hash; - } - - /// - /// Combines two 64 bit hashes generated by class into one. - /// - /// First hash value to be combined. - /// Second hash value to be combined. - /// - public static long Combine64(long left, long right) - { - unchecked - { - return (left ^ right) * fnvPrimeA64Bit; - } - } - } -}