Hash.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. // taken from and removed unused methods
  5. // https://github.com/dotnet/roslyn/blob/8a7ca9af3360ef388b6dad61c95e2d0629d7a032/src/Compilers/Core/Portable/InternalUtilities/Hash.cs
  6. using System.Runtime.CompilerServices;
  7. namespace Jint.Extensions;
  8. internal static class Hash
  9. {
  10. /// <summary>
  11. /// The offset bias value used in the FNV-1a algorithm
  12. /// See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
  13. /// </summary>
  14. private const int FnvOffsetBias = unchecked((int) 2166136261);
  15. /// <summary>
  16. /// The generative factor used in the FNV-1a algorithm
  17. /// See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
  18. /// </summary>
  19. private const int FnvPrime = 16777619;
  20. /// <summary>
  21. /// Compute the hashcode of a sub-string using FNV-1a
  22. /// See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
  23. /// Note: FNV-1a was developed and tuned for 8-bit sequences. We're using it here
  24. /// for 16-bit Unicode chars on the understanding that the majority of chars will
  25. /// fit into 8-bits and, therefore, the algorithm will retain its desirable traits
  26. /// for generating hash codes.
  27. /// </summary>
  28. internal static int GetFNVHashCode(ReadOnlySpan<char> data) => CombineFNVHash(FnvOffsetBias, data);
  29. /// <summary>
  30. /// Compute the hashcode of a string using FNV-1a
  31. /// See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
  32. /// </summary>
  33. /// <param name="text">The input string</param>
  34. /// <returns>The FNV-1a hash code of <paramref name="text"/></returns>
  35. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  36. internal static int GetFNVHashCode(string text) => CombineFNVHash(FnvOffsetBias, text);
  37. /// <summary>
  38. /// Compute the hashcode of a string using FNV-1a
  39. /// See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
  40. /// </summary>
  41. /// <param name="text">The input string</param>
  42. /// <returns>The FNV-1a hash code of <paramref name="text"/></returns>
  43. internal static int GetFNVHashCode(System.Text.StringBuilder text)
  44. {
  45. int hashCode = FnvOffsetBias;
  46. #if NETCOREAPP3_1_OR_GREATER
  47. foreach (var chunk in text.GetChunks())
  48. {
  49. hashCode = CombineFNVHash(hashCode, chunk.Span);
  50. }
  51. #else
  52. // StringBuilder.GetChunks is not available in this target framework. Since there is no other direct access
  53. // to the underlying storage spans of StringBuilder, we fall back to using slower per-character operations.
  54. int end = text.Length;
  55. for (int i = 0; i < end; i++)
  56. {
  57. hashCode = unchecked((hashCode ^ text[i]) * FnvPrime);
  58. }
  59. #endif
  60. return hashCode;
  61. }
  62. /// <summary>
  63. /// Combine a string with an existing FNV-1a hash code
  64. /// See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
  65. /// </summary>
  66. /// <param name="hashCode">The accumulated hash code</param>
  67. /// <param name="text">The string to combine</param>
  68. /// <returns>The result of combining <paramref name="hashCode"/> with <paramref name="text"/> using the FNV-1a algorithm</returns>
  69. [MethodImpl(MethodImplOptions.AggressiveInlining | (MethodImplOptions) 512)]
  70. private static int CombineFNVHash(int hashCode, string text)
  71. {
  72. foreach (char ch in text)
  73. {
  74. hashCode = unchecked((hashCode ^ ch) * FnvPrime);
  75. }
  76. return hashCode;
  77. }
  78. /// <summary>
  79. /// Combine a string with an existing FNV-1a hash code
  80. /// See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
  81. /// </summary>
  82. /// <param name="hashCode">The accumulated hash code</param>
  83. /// <param name="data">The string to combine</param>
  84. /// <returns>The result of combining <paramref name="hashCode"/> with <paramref name="data"/> using the FNV-1a algorithm</returns>
  85. [MethodImpl(MethodImplOptions.AggressiveInlining | (MethodImplOptions) 512)]
  86. private static int CombineFNVHash(int hashCode, ReadOnlySpan<char> data)
  87. {
  88. for (int i = 0; i < data.Length; i++)
  89. {
  90. hashCode = unchecked((hashCode ^ data[i]) * FnvPrime);
  91. }
  92. return hashCode;
  93. }
  94. }