// 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.
// taken from and removed unused methods
// https://github.com/dotnet/roslyn/blob/8a7ca9af3360ef388b6dad61c95e2d0629d7a032/src/Compilers/Core/Portable/InternalUtilities/Hash.cs
using System.Runtime.CompilerServices;
namespace Jint.Extensions;
internal static class Hash
{
///
/// The offset bias value used in the FNV-1a algorithm
/// See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
///
private const int FnvOffsetBias = unchecked((int) 2166136261);
///
/// The generative factor used in the FNV-1a algorithm
/// See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
///
private const int FnvPrime = 16777619;
///
/// Compute the hashcode of a sub-string using FNV-1a
/// See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
/// Note: FNV-1a was developed and tuned for 8-bit sequences. We're using it here
/// for 16-bit Unicode chars on the understanding that the majority of chars will
/// fit into 8-bits and, therefore, the algorithm will retain its desirable traits
/// for generating hash codes.
///
internal static int GetFNVHashCode(ReadOnlySpan data) => CombineFNVHash(FnvOffsetBias, data);
///
/// Compute the hashcode of a string using FNV-1a
/// See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
///
/// The input string
/// The FNV-1a hash code of
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int GetFNVHashCode(string text) => CombineFNVHash(FnvOffsetBias, text);
///
/// Compute the hashcode of a string using FNV-1a
/// See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
///
/// The input string
/// The FNV-1a hash code of
internal static int GetFNVHashCode(System.Text.StringBuilder text)
{
int hashCode = FnvOffsetBias;
#if NETCOREAPP3_1_OR_GREATER
foreach (var chunk in text.GetChunks())
{
hashCode = CombineFNVHash(hashCode, chunk.Span);
}
#else
// StringBuilder.GetChunks is not available in this target framework. Since there is no other direct access
// to the underlying storage spans of StringBuilder, we fall back to using slower per-character operations.
int end = text.Length;
for (int i = 0; i < end; i++)
{
hashCode = unchecked((hashCode ^ text[i]) * FnvPrime);
}
#endif
return hashCode;
}
///
/// Combine a string with an existing FNV-1a hash code
/// See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
///
/// The accumulated hash code
/// The string to combine
/// The result of combining with using the FNV-1a algorithm
[MethodImpl(MethodImplOptions.AggressiveInlining | (MethodImplOptions) 512)]
private static int CombineFNVHash(int hashCode, string text)
{
foreach (char ch in text)
{
hashCode = unchecked((hashCode ^ ch) * FnvPrime);
}
return hashCode;
}
///
/// Combine a string with an existing FNV-1a hash code
/// See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
///
/// The accumulated hash code
/// The string to combine
/// The result of combining with using the FNV-1a algorithm
[MethodImpl(MethodImplOptions.AggressiveInlining | (MethodImplOptions) 512)]
private static int CombineFNVHash(int hashCode, ReadOnlySpan data)
{
for (int i = 0; i < data.Length; i++)
{
hashCode = unchecked((hashCode ^ data[i]) * FnvPrime);
}
return hashCode;
}
}