mirror of https://github.com/tuyoogame/YooAsset
commit
05cb57db09
|
@ -41,6 +41,14 @@ namespace YooAsset.Editor
|
|||
manifest.PackageName = buildParameters.PackageName;
|
||||
manifest.PackageVersion = buildParameters.PackageVersion;
|
||||
manifest.BundleList = GetAllPackageBundle(context);
|
||||
int len = manifest.BundleList.Count;
|
||||
manifest.BundleListMap = new Dictionary<string, int>(len);
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
var item = manifest.BundleList[i];
|
||||
manifest.BundleListMap.Add(item.BundleName,i);
|
||||
}
|
||||
manifest.AssetList = GetAllPackageAsset(context, manifest);
|
||||
|
||||
// 更新Unity内置资源包的引用关系
|
||||
|
@ -87,7 +95,7 @@ namespace YooAsset.Editor
|
|||
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(buildParameters.PackageName, buildParameters.PackageVersion);
|
||||
string filePath = $"{packageOutputDirectory}/{fileName}";
|
||||
ManifestTools.SerializeToBinary(filePath, manifest);
|
||||
packageHash = HashUtility.FileMD5(filePath);
|
||||
packageHash = HashUtility.FileXXhash(filePath);
|
||||
BuildLogger.Log($"创建补丁清单文件:{filePath}");
|
||||
|
||||
ManifestContext manifestContext = new ManifestContext();
|
||||
|
@ -156,7 +164,7 @@ namespace YooAsset.Editor
|
|||
}
|
||||
private int[] GetAssetBundleDependIDs(int mainBundleID, BuildAssetInfo assetInfo, PackageManifest manifest)
|
||||
{
|
||||
List<int> result = new List<int>();
|
||||
HashSet<int> result = new HashSet<int>();
|
||||
foreach (var dependAssetInfo in assetInfo.AllDependAssetInfos)
|
||||
{
|
||||
if (dependAssetInfo.HasBundleName())
|
||||
|
@ -173,11 +181,17 @@ namespace YooAsset.Editor
|
|||
}
|
||||
private int GetAssetBundleID(string bundleName, PackageManifest manifest)
|
||||
{
|
||||
for (int index = 0; index < manifest.BundleList.Count; index++)
|
||||
// for (int index = 0; index < manifest.BundleList.Count; index++)
|
||||
// {
|
||||
// if (manifest.BundleList[index].BundleName == bundleName)
|
||||
// return index;
|
||||
// }
|
||||
|
||||
if (manifest.BundleListMap.ContainsKey(bundleName))
|
||||
{
|
||||
if (manifest.BundleList[index].BundleName == bundleName)
|
||||
return index;
|
||||
return manifest.BundleListMap[bundleName];
|
||||
}
|
||||
|
||||
throw new Exception($"Not found bundle name : {bundleName}");
|
||||
}
|
||||
|
||||
|
@ -212,7 +226,7 @@ namespace YooAsset.Editor
|
|||
List<string> conflictAssetPathList = dependBundles.Intersect(shaderBundleReferenceList).ToList();
|
||||
if (conflictAssetPathList.Count > 0)
|
||||
{
|
||||
List<int> newDependIDs = new List<int>(packageAsset.DependIDs);
|
||||
HashSet<int> newDependIDs = new HashSet<int>(packageAsset.DependIDs);
|
||||
if (newDependIDs.Contains(shaderBundleId) == false)
|
||||
newDependIDs.Add(shaderBundleId);
|
||||
packageAsset.DependIDs = newDependIDs.ToArray();
|
||||
|
@ -226,7 +240,7 @@ namespace YooAsset.Editor
|
|||
|
||||
// 更新资源包标签
|
||||
var packageBundle = manifest.BundleList[shaderBundleId];
|
||||
List<string> newTags = new List<string>(packageBundle.Tags);
|
||||
HashSet<string> newTags = new HashSet<string>(packageBundle.Tags);
|
||||
foreach (var tag in tagTemps)
|
||||
{
|
||||
if (newTags.Contains(tag) == false)
|
||||
|
@ -251,7 +265,7 @@ namespace YooAsset.Editor
|
|||
private readonly Dictionary<string, int> _cachedBundleID = new Dictionary<string, int>(10000);
|
||||
private readonly Dictionary<string, string[]> _cachedBundleDepends = new Dictionary<string, string[]>(10000);
|
||||
|
||||
private void UpdateScriptPipelineReference(PackageManifest manifest, TaskBuilding_SBP.BuildResultContext buildResultContext)
|
||||
private void UpdateScriptPipelineReference(PackageManifest manifest, TaskBuilding_SBP.BuildResultContext buildResultContext)
|
||||
{
|
||||
int progressValue;
|
||||
int totalCount = manifest.BundleList.Count;
|
||||
|
@ -263,7 +277,11 @@ namespace YooAsset.Editor
|
|||
{
|
||||
int bundleID = GetAssetBundleID(packageBundle.BundleName, manifest);
|
||||
_cachedBundleID.Add(packageBundle.BundleName, bundleID);
|
||||
EditorTools.DisplayProgressBar("缓存资源包索引", ++progressValue, totalCount);
|
||||
int pro = ++progressValue;
|
||||
if (pro % 100 == 0)
|
||||
{
|
||||
EditorTools.DisplayProgressBar("缓存资源包索引", pro, totalCount);
|
||||
}
|
||||
}
|
||||
EditorTools.ClearProgressBar();
|
||||
|
||||
|
@ -283,7 +301,11 @@ namespace YooAsset.Editor
|
|||
|
||||
var depends = buildResultContext.Results.BundleInfos[packageBundle.BundleName].Dependencies;
|
||||
_cachedBundleDepends.Add(packageBundle.BundleName, depends);
|
||||
EditorTools.DisplayProgressBar("缓存资源包依赖列表", ++progressValue, totalCount);
|
||||
int pro = ++progressValue;
|
||||
if (pro % 100 == 0)
|
||||
{
|
||||
EditorTools.DisplayProgressBar("缓存资源包依赖列表", pro, totalCount);
|
||||
}
|
||||
}
|
||||
EditorTools.ClearProgressBar();
|
||||
|
||||
|
@ -291,7 +313,11 @@ namespace YooAsset.Editor
|
|||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
packageBundle.ReferenceIDs = GetBundleRefrenceIDs(manifest, packageBundle);
|
||||
EditorTools.DisplayProgressBar("计算资源包引用关系", ++progressValue, totalCount);
|
||||
int pro = ++progressValue;
|
||||
if (pro % 100 == 0)
|
||||
{
|
||||
EditorTools.DisplayProgressBar("计算资源包引用关系", pro, totalCount);
|
||||
}
|
||||
}
|
||||
EditorTools.ClearProgressBar();
|
||||
}
|
||||
|
@ -307,7 +333,11 @@ namespace YooAsset.Editor
|
|||
{
|
||||
int bundleID = GetAssetBundleID(packageBundle.BundleName, manifest);
|
||||
_cachedBundleID.Add(packageBundle.BundleName, bundleID);
|
||||
EditorTools.DisplayProgressBar("缓存资源包索引", ++progressValue, totalCount);
|
||||
int pro = ++progressValue;
|
||||
if (pro % 100 == 0)
|
||||
{
|
||||
EditorTools.DisplayProgressBar("缓存资源包索引", pro, totalCount);
|
||||
}
|
||||
}
|
||||
EditorTools.ClearProgressBar();
|
||||
|
||||
|
@ -324,7 +354,11 @@ namespace YooAsset.Editor
|
|||
|
||||
var depends = buildResultContext.UnityManifest.GetDirectDependencies(packageBundle.BundleName);
|
||||
_cachedBundleDepends.Add(packageBundle.BundleName, depends);
|
||||
EditorTools.DisplayProgressBar("缓存资源包依赖列表", ++progressValue, totalCount);
|
||||
int pro = ++progressValue;
|
||||
if (pro % 100 == 0)
|
||||
{
|
||||
EditorTools.DisplayProgressBar("缓存资源包依赖列表", pro, totalCount);
|
||||
}
|
||||
}
|
||||
EditorTools.ClearProgressBar();
|
||||
|
||||
|
@ -333,7 +367,11 @@ namespace YooAsset.Editor
|
|||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
packageBundle.ReferenceIDs = GetBundleRefrenceIDs(manifest, packageBundle);
|
||||
EditorTools.DisplayProgressBar("计算资源包引用关系", ++progressValue, totalCount);
|
||||
int pro = ++progressValue;
|
||||
if (pro%100==0)
|
||||
{
|
||||
EditorTools.DisplayProgressBar("计算资源包引用关系", ++progressValue, totalCount);
|
||||
}
|
||||
}
|
||||
EditorTools.ClearProgressBar();
|
||||
}
|
||||
|
@ -344,7 +382,7 @@ namespace YooAsset.Editor
|
|||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
string bundleName = packageBundle.BundleName;
|
||||
if (bundleName == targetBundle.BundleName)
|
||||
if (packageBundle.Equals(targetBundle) || packageBundle.IsRawFile)
|
||||
continue;
|
||||
|
||||
string[] dependencies = GetCachedBundleDepends(bundleName);
|
||||
|
@ -354,7 +392,7 @@ namespace YooAsset.Editor
|
|||
}
|
||||
}
|
||||
|
||||
List<int> result = new List<int>();
|
||||
HashSet<int> result = new HashSet<int>();
|
||||
foreach (var bundleName in referenceList)
|
||||
{
|
||||
int bundleID = GetCachedBundleID(bundleName);
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace YooAsset.Editor
|
|||
if (bundleInfo.IsRawFile)
|
||||
{
|
||||
string filePath = bundleInfo.PackageSourceFilePath;
|
||||
return HashUtility.FileMD5(filePath);
|
||||
return HashUtility.FileXXhash(filePath);
|
||||
}
|
||||
|
||||
if (parameters.BuildPipeline == EBuildPipeline.BuiltinBuildPipeline)
|
||||
|
@ -132,7 +132,7 @@ namespace YooAsset.Editor
|
|||
if (buildMode == EBuildMode.DryRunBuild || buildMode == EBuildMode.SimulateBuild)
|
||||
return "00000000000000000000000000000000"; //32位
|
||||
else
|
||||
return HashUtility.FileMD5(filePath);
|
||||
return HashUtility.FileXXhash(filePath);
|
||||
}
|
||||
private string GetBundleFileCRC(string filePath, BuildParametersContext buildParametersContext)
|
||||
{
|
||||
|
|
|
@ -153,7 +153,7 @@ namespace YooAsset.Editor
|
|||
guids = AssetDatabase.FindAssets($"t:{searchType}", searchInFolders);
|
||||
|
||||
// 注意:AssetDatabase.FindAssets()可能会获取到重复的资源
|
||||
List<string> result = new List<string>();
|
||||
HashSet<string> result = new HashSet<string>();
|
||||
for (int i = 0; i < guids.Length; i++)
|
||||
{
|
||||
string guid = guids[i];
|
||||
|
|
|
@ -77,7 +77,7 @@ namespace YooAsset
|
|||
return;
|
||||
}
|
||||
|
||||
string fileHash = HashUtility.FileMD5(_manifestFilePath);
|
||||
string fileHash = HashUtility.FileXXhash(_manifestFilePath);
|
||||
if (fileHash != _queryCachePackageHashOp.PackageHash)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
|
|
|
@ -57,6 +57,8 @@ namespace YooAsset
|
|||
/// </summary>
|
||||
public List<PackageBundle> BundleList = new List<PackageBundle>();
|
||||
|
||||
public Dictionary<string, int> BundleListMap;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 资源包集合(提供BundleName获取PackageBundle)
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 626314312007949aebb542dcbbfe1a78
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
|
@ -0,0 +1,33 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f9ed697de8b5f18478c683c64e889512
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using Standart.Hash.xxHash;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
|
@ -281,6 +282,28 @@ namespace YooAsset
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取文件的XXXhash32
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
public static string FileXXhash(string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return xxHash32.ComputeHash(fs).ToString("x8");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
YooLogger.Exception(e);
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据流的MD5
|
||||
/// </summary>
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
{
|
||||
"name": "YooAsset",
|
||||
"rootNamespace": "",
|
||||
"references": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"allowUnsafeCode": true,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 99e361f80e17cb540a43e670a09a4745
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,260 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
public static class Utils
|
||||
{
|
||||
public static Guid ToGuid(this uint128 value)
|
||||
{
|
||||
var a = (Int32) (value.low64);
|
||||
var b = (Int16) (value.low64 >> 32);
|
||||
var c = (Int16) (value.low64 >> 48);
|
||||
|
||||
var d = (Byte) (value.high64);
|
||||
var e = (Byte) (value.high64 >> 8);
|
||||
var f = (Byte) (value.high64 >> 16);
|
||||
var g = (Byte) (value.high64 >> 24);
|
||||
var h = (Byte) (value.high64 >> 32);
|
||||
var i = (Byte) (value.high64 >> 40);
|
||||
var j = (Byte) (value.high64 >> 48);
|
||||
var k = (Byte) (value.high64 >> 56);
|
||||
|
||||
return new Guid(a, b, c, d, e, f,g, h, i, j, k);
|
||||
}
|
||||
|
||||
public static byte[] ToBytes(this uint128 value)
|
||||
{
|
||||
// allocation
|
||||
byte[] bytes = new byte[sizeof(ulong) * 2];
|
||||
Unsafe.As<byte, ulong>(ref bytes[0]) = value.low64;
|
||||
Unsafe.As<byte, ulong>(ref bytes[8]) = value.high64;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static unsafe void BlockCopy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int count)
|
||||
{
|
||||
Debug.Assert(src != null);
|
||||
Debug.Assert(dst != null);
|
||||
Debug.Assert(srcOffset >= 0 && srcOffset < src.Length);
|
||||
Debug.Assert(dstOffset >= 0 && dstOffset < dst.Length);
|
||||
Debug.Assert(count >= 0);
|
||||
Debug.Assert(count + srcOffset <= src.Length);
|
||||
Debug.Assert(count + dstOffset <= dst.Length);
|
||||
|
||||
fixed (byte* pSrc = &src[srcOffset])
|
||||
fixed (byte* pDst = &dst[dstOffset])
|
||||
{
|
||||
byte* ptrSrc = pSrc;
|
||||
byte* ptrDst = pDst;
|
||||
|
||||
SMALLTABLE:
|
||||
switch (count)
|
||||
{
|
||||
case 0:
|
||||
return;
|
||||
case 1:
|
||||
*ptrDst = *ptrSrc;
|
||||
return;
|
||||
case 2:
|
||||
*(short*)ptrDst = *(short*)ptrSrc;
|
||||
return;
|
||||
case 3:
|
||||
*(short*)(ptrDst + 0) = *(short*)(ptrSrc + 0);
|
||||
*(ptrDst + 2) = *(ptrSrc + 2);
|
||||
return;
|
||||
case 4:
|
||||
*(int*)ptrDst = *(int*)ptrSrc;
|
||||
return;
|
||||
case 5:
|
||||
*(int*)(ptrDst + 0) = *(int*)(ptrSrc + 0);
|
||||
*(ptrDst + 4) = *(ptrSrc + 4);
|
||||
return;
|
||||
case 6:
|
||||
*(int*)(ptrDst + 0) = *(int*)(ptrSrc + 0);
|
||||
*(short*)(ptrDst + 4) = *(short*)(ptrSrc + 4);
|
||||
return;
|
||||
case 7:
|
||||
*(int*)(ptrDst + 0) = *(int*)(ptrSrc + 0);
|
||||
*(short*)(ptrDst + 4) = *(short*)(ptrSrc + 4);
|
||||
*(ptrDst + 6) = *(ptrSrc + 6);
|
||||
return;
|
||||
case 8:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
return;
|
||||
case 9:
|
||||
*(long*)(ptrDst + 0) = *(long*)(ptrSrc + 0);
|
||||
*(ptrDst + 8) = *(ptrSrc + 8);
|
||||
return;
|
||||
case 10:
|
||||
*(long*)(ptrDst + 0) = *(long*)(ptrSrc + 0);
|
||||
*(short*)(ptrDst + 8) = *(short*)(ptrSrc + 8);
|
||||
return;
|
||||
case 11:
|
||||
*(long*)(ptrDst + 0) = *(long*)(ptrSrc + 0);
|
||||
*(short*)(ptrDst + 8) = *(short*)(ptrSrc + 8);
|
||||
*(ptrDst + 10) = *(ptrSrc + 10);
|
||||
return;
|
||||
case 12:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(int*)(ptrDst + 8) = *(int*)(ptrSrc + 8);
|
||||
return;
|
||||
case 13:
|
||||
*(long*)(ptrDst + 0) = *(long*)(ptrSrc + 0);
|
||||
*(int*)(ptrDst + 8) = *(int*)(ptrSrc + 8);
|
||||
*(ptrDst + 12) = *(ptrSrc + 12);
|
||||
return;
|
||||
case 14:
|
||||
*(long*)(ptrDst + 0) = *(long*)(ptrSrc + 0);
|
||||
*(int*)(ptrDst + 8) = *(int*)(ptrSrc + 8);
|
||||
*(short*)(ptrDst + 12) = *(short*)(ptrSrc + 12);
|
||||
return;
|
||||
case 15:
|
||||
*(long*)(ptrDst + 0) = *(long*)(ptrSrc + 0);
|
||||
*(int*)(ptrDst + 8) = *(int*)(ptrSrc + 8);
|
||||
*(short*)(ptrDst + 12) = *(short*)(ptrSrc + 12);
|
||||
*(ptrDst + 14) = *(ptrSrc + 14);
|
||||
return;
|
||||
case 16:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
return;
|
||||
case 17:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(ptrDst + 16) = *(ptrSrc + 16);
|
||||
return;
|
||||
case 18:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(short*)(ptrDst + 16) = *(short*)(ptrSrc + 16);
|
||||
return;
|
||||
case 19:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(short*)(ptrDst + 16) = *(short*)(ptrSrc + 16);
|
||||
*(ptrDst + 18) = *(ptrSrc + 18);
|
||||
return;
|
||||
case 20:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(int*)(ptrDst + 16) = *(int*)(ptrSrc + 16);
|
||||
return;
|
||||
|
||||
case 21:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(int*)(ptrDst + 16) = *(int*)(ptrSrc + 16);
|
||||
*(ptrDst + 20) = *(ptrSrc + 20);
|
||||
return;
|
||||
case 22:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(int*)(ptrDst + 16) = *(int*)(ptrSrc + 16);
|
||||
*(short*)(ptrDst + 20) = *(short*)(ptrSrc + 20);
|
||||
return;
|
||||
case 23:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(int*)(ptrDst + 16) = *(int*)(ptrSrc + 16);
|
||||
*(short*)(ptrDst + 20) = *(short*)(ptrSrc + 20);
|
||||
*(ptrDst + 22) = *(ptrSrc + 22);
|
||||
return;
|
||||
case 24:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(long*)(ptrDst + 16) = *(long*)(ptrSrc + 16);
|
||||
return;
|
||||
case 25:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(long*)(ptrDst + 16) = *(long*)(ptrSrc + 16);
|
||||
*(ptrDst + 24) = *(ptrSrc + 24);
|
||||
return;
|
||||
case 26:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(long*)(ptrDst + 16) = *(long*)(ptrSrc + 16);
|
||||
*(short*)(ptrDst + 24) = *(short*)(ptrSrc + 24);
|
||||
return;
|
||||
case 27:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(long*)(ptrDst + 16) = *(long*)(ptrSrc + 16);
|
||||
*(short*)(ptrDst + 24) = *(short*)(ptrSrc + 24);
|
||||
*(ptrDst + 26) = *(ptrSrc + 26);
|
||||
return;
|
||||
case 28:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(long*)(ptrDst + 16) = *(long*)(ptrSrc + 16);
|
||||
*(int*)(ptrDst + 24) = *(int*)(ptrSrc + 24);
|
||||
return;
|
||||
case 29:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(long*)(ptrDst + 16) = *(long*)(ptrSrc + 16);
|
||||
*(int*)(ptrDst + 24) = *(int*)(ptrSrc + 24);
|
||||
*(ptrDst + 28) = *(ptrSrc + 28);
|
||||
return;
|
||||
case 30:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(long*)(ptrDst + 16) = *(long*)(ptrSrc + 16);
|
||||
*(int*)(ptrDst + 24) = *(int*)(ptrSrc + 24);
|
||||
*(short*)(ptrDst + 28) = *(short*)(ptrSrc + 28);
|
||||
return;
|
||||
case 31:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(long*)(ptrDst + 16) = *(long*)(ptrSrc + 16);
|
||||
*(int*)(ptrDst + 24) = *(int*)(ptrSrc + 24);
|
||||
*(short*)(ptrDst + 28) = *(short*)(ptrSrc + 28);
|
||||
*(ptrDst + 30) = *(ptrSrc + 30);
|
||||
return;
|
||||
case 32:
|
||||
*(long*)ptrDst = *(long*)ptrSrc;
|
||||
*(long*)(ptrDst + 8) = *(long*)(ptrSrc + 8);
|
||||
*(long*)(ptrDst + 16) = *(long*)(ptrSrc + 16);
|
||||
*(long*)(ptrDst + 24) = *(long*)(ptrSrc + 24);
|
||||
return;
|
||||
}
|
||||
|
||||
long* lpSrc = (long*)ptrSrc;
|
||||
long* ldSrc = (long*)ptrDst;
|
||||
while (count >= 64)
|
||||
{
|
||||
*(ldSrc + 0) = *(lpSrc + 0);
|
||||
*(ldSrc + 1) = *(lpSrc + 1);
|
||||
*(ldSrc + 2) = *(lpSrc + 2);
|
||||
*(ldSrc + 3) = *(lpSrc + 3);
|
||||
*(ldSrc + 4) = *(lpSrc + 4);
|
||||
*(ldSrc + 5) = *(lpSrc + 5);
|
||||
*(ldSrc + 6) = *(lpSrc + 6);
|
||||
*(ldSrc + 7) = *(lpSrc + 7);
|
||||
if (count == 64)
|
||||
return;
|
||||
count -= 64;
|
||||
lpSrc += 8;
|
||||
ldSrc += 8;
|
||||
}
|
||||
if (count > 32)
|
||||
{
|
||||
*(ldSrc + 0) = *(lpSrc + 0);
|
||||
*(ldSrc + 1) = *(lpSrc + 1);
|
||||
*(ldSrc + 2) = *(lpSrc + 2);
|
||||
*(ldSrc + 3) = *(lpSrc + 3);
|
||||
count -= 32;
|
||||
lpSrc += 4;
|
||||
ldSrc += 4;
|
||||
}
|
||||
|
||||
ptrSrc = (byte*)lpSrc;
|
||||
ptrDst = (byte*)ldSrc;
|
||||
goto SMALLTABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 07b97cff0161f014f857bb23a25d73a9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* This is the auto generated code.
|
||||
* All function calls are inlined in XXH32
|
||||
* Please don't try to analyze it.
|
||||
*/
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
public partial class xxHash32
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint __inline__XXH32(byte* input, int len, uint seed)
|
||||
{
|
||||
uint h32;
|
||||
|
||||
if (len >= 16)
|
||||
{
|
||||
byte* end = input + len;
|
||||
byte* limit = end - 15;
|
||||
|
||||
uint v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2;
|
||||
uint v2 = seed + XXH_PRIME32_2;
|
||||
uint v3 = seed + 0;
|
||||
uint v4 = seed - XXH_PRIME32_1;
|
||||
|
||||
do
|
||||
{
|
||||
var reg1 = *((uint*)(input + 0));
|
||||
var reg2 = *((uint*)(input + 4));
|
||||
var reg3 = *((uint*)(input + 8));
|
||||
var reg4 = *((uint*)(input + 12));
|
||||
|
||||
// XXH32_round
|
||||
v1 += reg1 * XXH_PRIME32_2;
|
||||
v1 = (v1 << 13) | (v1 >> (32 - 13));
|
||||
v1 *= XXH_PRIME32_1;
|
||||
|
||||
// XXH32_round
|
||||
v2 += reg2 * XXH_PRIME32_2;
|
||||
v2 = (v2 << 13) | (v2 >> (32 - 13));
|
||||
v2 *= XXH_PRIME32_1;
|
||||
|
||||
// XXH32_round
|
||||
v3 += reg3 * XXH_PRIME32_2;
|
||||
v3 = (v3 << 13) | (v3 >> (32 - 13));
|
||||
v3 *= XXH_PRIME32_1;
|
||||
|
||||
// XXH32_round
|
||||
v4 += reg4 * XXH_PRIME32_2;
|
||||
v4 = (v4 << 13) | (v4 >> (32 - 13));
|
||||
v4 *= XXH_PRIME32_1;
|
||||
|
||||
input += 16;
|
||||
} while (input < limit);
|
||||
|
||||
h32 = ((v1 << 1) | (v1 >> (32 - 1))) +
|
||||
((v2 << 7) | (v2 >> (32 - 7))) +
|
||||
((v3 << 12) | (v3 >> (32 - 12))) +
|
||||
((v4 << 18) | (v4 >> (32 - 18)));
|
||||
}
|
||||
else
|
||||
{
|
||||
h32 = seed + XXH_PRIME32_5;
|
||||
}
|
||||
|
||||
h32 += (uint) len;
|
||||
|
||||
// XXH32_finalize
|
||||
len &= 15;
|
||||
while (len >= 4)
|
||||
{
|
||||
h32 += *((uint*) input) * XXH_PRIME32_3;
|
||||
input += 4;
|
||||
h32 = ((h32 << 17) | (h32 >> (32 - 17))) * XXH_PRIME32_4;
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
h32 += *((byte*) input) * XXH_PRIME32_5;
|
||||
++input;
|
||||
h32 = ((h32 << 11) | (h32 >> (32 - 11))) * XXH_PRIME32_1;
|
||||
--len;
|
||||
}
|
||||
|
||||
// XXH32_avalanche
|
||||
h32 ^= h32 >> 15;
|
||||
h32 *= XXH_PRIME32_2;
|
||||
h32 ^= h32 >> 13;
|
||||
h32 *= XXH_PRIME32_3;
|
||||
h32 ^= h32 >> 16;
|
||||
|
||||
return h32;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void __inline__XXH32_stream_process(byte[] input, int len, ref uint v1, ref uint v2, ref uint v3, ref uint v4)
|
||||
{
|
||||
fixed (byte* pData = &input[0])
|
||||
{
|
||||
byte* ptr = pData;
|
||||
byte* limit = ptr + len;
|
||||
|
||||
do
|
||||
{
|
||||
var reg1 = *((uint*)(ptr + 0));
|
||||
var reg2 = *((uint*)(ptr + 4));
|
||||
var reg3 = *((uint*)(ptr + 8));
|
||||
var reg4 = *((uint*)(ptr + 12));
|
||||
|
||||
// XXH32_round
|
||||
v1 += reg1 * XXH_PRIME32_2;
|
||||
v1 = (v1 << 13) | (v1 >> (32 - 13));
|
||||
v1 *= XXH_PRIME32_1;
|
||||
|
||||
// XXH32_round
|
||||
v2 += reg2 * XXH_PRIME32_2;
|
||||
v2 = (v2 << 13) | (v2 >> (32 - 13));
|
||||
v2 *= XXH_PRIME32_1;
|
||||
|
||||
// XXH32_round
|
||||
v3 += reg3 * XXH_PRIME32_2;
|
||||
v3 = (v3 << 13) | (v3 >> (32 - 13));
|
||||
v3 *= XXH_PRIME32_1;
|
||||
|
||||
// XXH32_round
|
||||
v4 += reg4 * XXH_PRIME32_2;
|
||||
v4 = (v4 << 13) | (v4 >> (32 - 13));
|
||||
v4 *= XXH_PRIME32_1;
|
||||
|
||||
ptr += 16;
|
||||
|
||||
} while (ptr < limit);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint __inline__XXH32_stream_finalize(byte[] input, int len, ref uint v1, ref uint v2, ref uint v3, ref uint v4, long length, uint seed)
|
||||
{
|
||||
fixed (byte* pData = &input[0])
|
||||
{
|
||||
byte* ptr = pData;
|
||||
uint h32;
|
||||
|
||||
if (length >= 16)
|
||||
{
|
||||
h32 = ((v1 << 1) | (v1 >> (32 - 1))) +
|
||||
((v2 << 7) | (v2 >> (32 - 7))) +
|
||||
((v3 << 12) | (v3 >> (32 - 12))) +
|
||||
((v4 << 18) | (v4 >> (32 - 18)));
|
||||
}
|
||||
else
|
||||
{
|
||||
h32 = seed + XXH_PRIME32_5;
|
||||
}
|
||||
|
||||
h32 += (uint)length;
|
||||
|
||||
// XXH32_finalize
|
||||
len &= 15;
|
||||
while (len >= 4)
|
||||
{
|
||||
h32 += *((uint*)ptr) * XXH_PRIME32_3;
|
||||
ptr += 4;
|
||||
h32 = ((h32 << 17) | (h32 >> (32 - 17))) * XXH_PRIME32_4;
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
h32 += *((byte*)ptr) * XXH_PRIME32_5;
|
||||
ptr++;
|
||||
h32 = ((h32 << 11) | (h32 >> (32 - 11))) * XXH_PRIME32_1;
|
||||
len--;
|
||||
}
|
||||
|
||||
// XXH32_avalanche
|
||||
h32 ^= h32 >> 15;
|
||||
h32 *= XXH_PRIME32_2;
|
||||
h32 ^= h32 >> 13;
|
||||
h32 *= XXH_PRIME32_3;
|
||||
h32 ^= h32 >> 16;
|
||||
|
||||
return h32;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7bd3966e4951b294d8cda4a41bb4b690
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
* This is the auto generated code.
|
||||
* All function calls are inlined in XXH64
|
||||
* Please don't try to analyze it.
|
||||
*/
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
public partial class xxHash64
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong __inline__XXH64(byte* input, int len, ulong seed)
|
||||
{
|
||||
ulong h64;
|
||||
|
||||
if (len >= 32)
|
||||
{
|
||||
byte* end = input + len;
|
||||
byte* limit = end - 31;
|
||||
|
||||
ulong v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2;
|
||||
ulong v2 = seed + XXH_PRIME64_2;
|
||||
ulong v3 = seed + 0;
|
||||
ulong v4 = seed - XXH_PRIME64_1;
|
||||
|
||||
do
|
||||
{
|
||||
var reg1 = *((ulong*)(input + 0));
|
||||
var reg2 = *((ulong*)(input + 8));
|
||||
var reg3 = *((ulong*)(input + 16));
|
||||
var reg4 = *((ulong*)(input + 24));
|
||||
|
||||
// XXH64_round
|
||||
v1 += reg1 * XXH_PRIME64_2;
|
||||
v1 = (v1 << 31) | (v1 >> (64 - 31));
|
||||
v1 *= XXH_PRIME64_1;
|
||||
|
||||
// XXH64_round
|
||||
v2 += reg2 * XXH_PRIME64_2;
|
||||
v2 = (v2 << 31) | (v2 >> (64 - 31));
|
||||
v2 *= XXH_PRIME64_1;
|
||||
|
||||
// XXH64_round
|
||||
v3 += reg3 * XXH_PRIME64_2;
|
||||
v3 = (v3 << 31) | (v3 >> (64 - 31));
|
||||
v3 *= XXH_PRIME64_1;
|
||||
|
||||
// XXH64_round
|
||||
v4 += reg4 * XXH_PRIME64_2;
|
||||
v4 = (v4 << 31) | (v4 >> (64 - 31));
|
||||
v4 *= XXH_PRIME64_1;
|
||||
input += 32;
|
||||
} while (input < limit);
|
||||
|
||||
h64 = ((v1 << 1) | (v1 >> (64 - 1))) +
|
||||
((v2 << 7) | (v2 >> (64 - 7))) +
|
||||
((v3 << 12) | (v3 >> (64 - 12))) +
|
||||
((v4 << 18) | (v4 >> (64 - 18)));
|
||||
|
||||
// XXH64_mergeRound
|
||||
v1 *= XXH_PRIME64_2;
|
||||
v1 = (v1 << 31) | (v1 >> (64 - 31));
|
||||
v1 *= XXH_PRIME64_1;
|
||||
h64 ^= v1;
|
||||
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||
|
||||
// XXH64_mergeRound
|
||||
v2 *= XXH_PRIME64_2;
|
||||
v2 = (v2 << 31) | (v2 >> (64 - 31));
|
||||
v2 *= XXH_PRIME64_1;
|
||||
h64 ^= v2;
|
||||
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||
|
||||
// XXH64_mergeRound
|
||||
v3 *= XXH_PRIME64_2;
|
||||
v3 = (v3 << 31) | (v3 >> (64 - 31));
|
||||
v3 *= XXH_PRIME64_1;
|
||||
h64 ^= v3;
|
||||
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||
|
||||
// XXH64_mergeRound
|
||||
v4 *= XXH_PRIME64_2;
|
||||
v4 = (v4 << 31) | (v4 >> (64 - 31));
|
||||
v4 *= XXH_PRIME64_1;
|
||||
h64 ^= v4;
|
||||
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
h64 = seed + XXH_PRIME64_5;
|
||||
}
|
||||
|
||||
h64 += (ulong) len;
|
||||
|
||||
// XXH64_finalize
|
||||
len &= 31;
|
||||
while (len >= 8) {
|
||||
ulong k1 = XXH64_round(0, *(ulong*)input);
|
||||
input += 8;
|
||||
h64 ^= k1;
|
||||
h64 = XXH_rotl64(h64,27) * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||
len -= 8;
|
||||
}
|
||||
if (len >= 4) {
|
||||
h64 ^= *(uint*)input * XXH_PRIME64_1;
|
||||
input += 4;
|
||||
h64 = XXH_rotl64(h64, 23) * XXH_PRIME64_2 + XXH_PRIME64_3;
|
||||
len -= 4;
|
||||
}
|
||||
while (len > 0) {
|
||||
h64 ^= (*input++) * XXH_PRIME64_5;
|
||||
h64 = XXH_rotl64(h64, 11) * XXH_PRIME64_1;
|
||||
--len;
|
||||
}
|
||||
|
||||
// XXH64_avalanche
|
||||
h64 ^= h64 >> 33;
|
||||
h64 *= XXH_PRIME64_2;
|
||||
h64 ^= h64 >> 29;
|
||||
h64 *= XXH_PRIME64_3;
|
||||
h64 ^= h64 >> 32;
|
||||
|
||||
return h64;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void __inline__XXH64_stream_process(byte[] input, int len, ref ulong v1, ref ulong v2, ref ulong v3,
|
||||
ref ulong v4)
|
||||
{
|
||||
fixed (byte* pData = &input[0])
|
||||
{
|
||||
byte* ptr = pData;
|
||||
byte* limit = ptr + len;
|
||||
|
||||
do
|
||||
{
|
||||
var reg1 = *((ulong*)(ptr + 0));
|
||||
var reg2 = *((ulong*)(ptr + 8));
|
||||
var reg3 = *((ulong*)(ptr + 16));
|
||||
var reg4 = *((ulong*)(ptr + 24));
|
||||
|
||||
// XXH64_round
|
||||
v1 += reg1 * XXH_PRIME64_2;
|
||||
v1 = (v1 << 31) | (v1 >> (64 - 31));
|
||||
v1 *= XXH_PRIME64_1;
|
||||
|
||||
// XXH64_round
|
||||
v2 += reg2 * XXH_PRIME64_2;
|
||||
v2 = (v2 << 31) | (v2 >> (64 - 31));
|
||||
v2 *= XXH_PRIME64_1;
|
||||
|
||||
// XXH64_round
|
||||
v3 += reg3 * XXH_PRIME64_2;
|
||||
v3 = (v3 << 31) | (v3 >> (64 - 31));
|
||||
v3 *= XXH_PRIME64_1;
|
||||
|
||||
// XXH64_round
|
||||
v4 += reg4 * XXH_PRIME64_2;
|
||||
v4 = (v4 << 31) | (v4 >> (64 - 31));
|
||||
v4 *= XXH_PRIME64_1;
|
||||
ptr += 32;
|
||||
} while (ptr < limit);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong __inline__XXH64_stream_finalize(byte[] input, int len, ref ulong v1, ref ulong v2, ref ulong v3,
|
||||
ref ulong v4, long length, ulong seed)
|
||||
{
|
||||
fixed (byte* pData = &input[0])
|
||||
{
|
||||
byte* ptr = pData;
|
||||
byte* end = pData + len;
|
||||
ulong h64;
|
||||
|
||||
if (length >= 32)
|
||||
{
|
||||
h64 = ((v1 << 1) | (v1 >> (64 - 1))) +
|
||||
((v2 << 7) | (v2 >> (64 - 7))) +
|
||||
((v3 << 12) | (v3 >> (64 - 12))) +
|
||||
((v4 << 18) | (v4 >> (64 - 18)));
|
||||
|
||||
// XXH64_mergeRound
|
||||
v1 *= XXH_PRIME64_2;
|
||||
v1 = (v1 << 31) | (v1 >> (64 - 31));
|
||||
v1 *= XXH_PRIME64_1;
|
||||
h64 ^= v1;
|
||||
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||
|
||||
// XXH64_mergeRound
|
||||
v2 *= XXH_PRIME64_2;
|
||||
v2 = (v2 << 31) | (v2 >> (64 - 31));
|
||||
v2 *= XXH_PRIME64_1;
|
||||
h64 ^= v2;
|
||||
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||
|
||||
// XXH64_mergeRound
|
||||
v3 *= XXH_PRIME64_2;
|
||||
v3 = (v3 << 31) | (v3 >> (64 - 31));
|
||||
v3 *= XXH_PRIME64_1;
|
||||
h64 ^= v3;
|
||||
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||
|
||||
// XXH64_mergeRound
|
||||
v4 *= XXH_PRIME64_2;
|
||||
v4 = (v4 << 31) | (v4 >> (64 - 31));
|
||||
v4 *= XXH_PRIME64_1;
|
||||
h64 ^= v4;
|
||||
h64 = h64 * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
h64 = seed + XXH_PRIME64_5;
|
||||
}
|
||||
|
||||
h64 += (ulong) length;
|
||||
|
||||
// XXH64_finalize
|
||||
len &= 31;
|
||||
while (len >= 8) {
|
||||
ulong k1 = XXH64_round(0, *(ulong*)ptr);
|
||||
ptr += 8;
|
||||
h64 ^= k1;
|
||||
h64 = XXH_rotl64(h64,27) * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||
len -= 8;
|
||||
}
|
||||
if (len >= 4) {
|
||||
h64 ^= *(uint*)ptr * XXH_PRIME64_1;
|
||||
ptr += 4;
|
||||
h64 = XXH_rotl64(h64, 23) * XXH_PRIME64_2 + XXH_PRIME64_3;
|
||||
len -= 4;
|
||||
}
|
||||
while (len > 0) {
|
||||
h64 ^= (*ptr++) * XXH_PRIME64_5;
|
||||
h64 = XXH_rotl64(h64, 11) * XXH_PRIME64_1;
|
||||
--len;
|
||||
}
|
||||
|
||||
// XXH64_avalanche
|
||||
h64 ^= h64 >> 33;
|
||||
h64 *= XXH_PRIME64_2;
|
||||
h64 ^= h64 >> 29;
|
||||
h64 *= XXH_PRIME64_3;
|
||||
h64 ^= h64 >> 32;
|
||||
|
||||
return h64;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 81174f2235c739845b98c1eed4778f17
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,125 @@
|
|||
// ReSharper disable InconsistentNaming
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
public static partial class xxHash128
|
||||
{
|
||||
private static readonly ulong XXH_PRIME64_1 = 11400714785074694791UL;
|
||||
private static readonly ulong XXH_PRIME64_2 = 14029467366897019727UL;
|
||||
private static readonly ulong XXH_PRIME64_3 = 1609587929392839161UL;
|
||||
private static readonly ulong XXH_PRIME64_4 = 9650029242287828579UL;
|
||||
private static readonly ulong XXH_PRIME64_5 = 2870177450012600261UL;
|
||||
|
||||
private static readonly uint XXH_PRIME32_1 = 2654435761U;
|
||||
private static readonly uint XXH_PRIME32_2 = 2246822519U;
|
||||
private static readonly uint XXH_PRIME32_3 = 3266489917U;
|
||||
private static readonly uint XXH_PRIME32_4 = 668265263U;
|
||||
private static readonly uint XXH_PRIME32_5 = 374761393U;
|
||||
|
||||
private static readonly int XXH_STRIPE_LEN = 64;
|
||||
private static readonly int XXH_ACC_NB = 8;
|
||||
private static readonly int XXH_SECRET_CONSUME_RATE = 8;
|
||||
private static readonly int XXH_SECRET_MERGEACCS_START = 11;
|
||||
private static readonly int XXH_SECRET_DEFAULT_SIZE = 192;
|
||||
private static readonly int XXH_SECRET_LASTACC_START = 7;
|
||||
|
||||
private static readonly byte MM_SHUFFLE_0_3_0_1 = 0b0011_0001;
|
||||
private static readonly byte MM_SHUFFLE_1_0_3_2 = 0b0100_1110;
|
||||
|
||||
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static uint XXH_rotl32(uint x, int r)
|
||||
{
|
||||
return (x << r) | (x >> (32 - r));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH_rotl64(ulong x, int r)
|
||||
{
|
||||
return (x << r) | (x >> (64 - r));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH_readLE64(byte* ptr)
|
||||
{
|
||||
return *(ulong*) ptr;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint XXH_readLE32(byte* ptr)
|
||||
{
|
||||
return *(uint*) ptr;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH_xorshift64(ulong v64, int shift)
|
||||
{
|
||||
return v64 ^ (v64 >> shift);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static uint XXH_swap32(uint x)
|
||||
{
|
||||
return ((x << 24) & 0xff000000 ) |
|
||||
((x << 8) & 0x00ff0000 ) |
|
||||
((x >> 8) & 0x0000ff00 ) |
|
||||
((x >> 24) & 0x000000ff );
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH_swap64(ulong x)
|
||||
{
|
||||
return ((x << 56) & 0xff00000000000000UL) |
|
||||
((x << 40) & 0x00ff000000000000UL) |
|
||||
((x << 24) & 0x0000ff0000000000UL) |
|
||||
((x << 8) & 0x000000ff00000000UL) |
|
||||
((x >> 8) & 0x00000000ff000000UL) |
|
||||
((x >> 24) & 0x0000000000ff0000UL) |
|
||||
((x >> 40) & 0x000000000000ff00UL) |
|
||||
((x >> 56) & 0x00000000000000ffUL);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH_mult32to64(ulong x, ulong y)
|
||||
{
|
||||
return (ulong)(uint)(x) * (ulong)(uint)(y);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static uint128 XXH_mult64to128(ulong lhs, ulong rhs)
|
||||
{
|
||||
|
||||
|
||||
return XXH_mult64to128_scalar(lhs, rhs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static uint128 XXH_mult64to128_scalar(ulong lhs, ulong rhs)
|
||||
{
|
||||
ulong lo_lo = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs & 0xFFFFFFFF);
|
||||
ulong hi_lo = XXH_mult32to64(lhs >> 32, rhs & 0xFFFFFFFF);
|
||||
ulong lo_hi = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs >> 32);
|
||||
ulong hi_hi = XXH_mult32to64(lhs >> 32, rhs >> 32);
|
||||
|
||||
ulong cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi;
|
||||
ulong upper = (hi_lo >> 32) + (cross >> 32) + hi_hi;
|
||||
ulong lower = (cross << 32) | (lo_lo & 0xFFFFFFFF);
|
||||
|
||||
uint128 r128;
|
||||
r128.low64 = lower;
|
||||
r128.high64 = upper;
|
||||
return r128;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH_writeLE64(byte* dst, ulong v64)
|
||||
{
|
||||
*(ulong*) dst = v64;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 45095bcca3212f441b4c38711f0ff93d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,452 @@
|
|||
// ReSharper disable InconsistentNaming
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
public static partial class xxHash128
|
||||
{
|
||||
private static readonly byte[] XXH3_SECRET =
|
||||
{
|
||||
0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,
|
||||
0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,
|
||||
0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21,
|
||||
0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c,
|
||||
0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3,
|
||||
0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8,
|
||||
0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d,
|
||||
0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64,
|
||||
0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb,
|
||||
0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e,
|
||||
0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce,
|
||||
0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,
|
||||
};
|
||||
|
||||
private static readonly ulong[] XXH3_INIT_ACC =
|
||||
{
|
||||
XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3,
|
||||
XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1
|
||||
};
|
||||
|
||||
private static readonly int XXH3_SECRET_SIZE_MIN = 136;
|
||||
private static readonly int XXH3_SECRET_DEFAULT_SIZE = 192;
|
||||
private static readonly int XXH3_MIDSIZE_MAX = 240;
|
||||
private static readonly int XXH3_MIDSIZE_STARTOFFSET = 3;
|
||||
private static readonly int XXH3_MIDSIZE_LASTOFFSET = 17;
|
||||
private static readonly int XXH3_ACC_SIZE = 64;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint128 XXH3_128bits_internal(byte* input, int len, ulong seed, byte* secret, int secretLen)
|
||||
{
|
||||
Debug.Assert(secretLen >= XXH3_SECRET_SIZE_MIN);
|
||||
|
||||
if (len <= 16)
|
||||
return XXH3_len_0to16_128b(input, len, secret, seed);
|
||||
if (len <= 128)
|
||||
return XXH3_len_17to128_128b(input, len, secret, secretLen, seed);
|
||||
if (len <= XXH3_MIDSIZE_MAX)
|
||||
return XXH3_len_129to240_128b(input, len, secret, secretLen, seed);
|
||||
|
||||
return XXH3_hashLong_128b_withSeed(input, len, secret, secretLen, seed);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint128 XXH3_len_0to16_128b(byte* input, int len, byte* secret, ulong seed)
|
||||
{
|
||||
Debug.Assert(len <= 16);
|
||||
|
||||
if (len > 8) return XXH3_len_9to16_128b(input, len, secret, seed);
|
||||
if (len >= 4) return XXH3_len_4to8_128b(input, len, secret, seed);
|
||||
if (len != 0) return XXH3_len_1to3_128b(input, len, secret, seed);
|
||||
|
||||
uint128 h128;
|
||||
ulong bitflipl = XXH_readLE64(secret + 64) ^ XXH_readLE64(secret + 72);
|
||||
ulong bitfliph = XXH_readLE64(secret + 80) ^ XXH_readLE64(secret + 88);
|
||||
h128.low64 = XXH64_avalanche(seed ^ bitflipl);
|
||||
h128.high64 = XXH64_avalanche(seed ^ bitfliph);
|
||||
return h128;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint128 XXH3_len_17to128_128b(byte* input, int len, byte* secret, int secretSize, ulong seed)
|
||||
{
|
||||
Debug.Assert(secretSize >= XXH3_SECRET_SIZE_MIN);
|
||||
Debug.Assert(16 < len && len <= 128);
|
||||
|
||||
uint128 acc;
|
||||
acc.low64 = (ulong) len * XXH_PRIME64_1;
|
||||
acc.high64 = 0;
|
||||
|
||||
if (len > 32) {
|
||||
if (len > 64) {
|
||||
if (len > 96) {
|
||||
acc = XXH128_mix32B(acc, input+48, input+len-64, secret+96, seed);
|
||||
}
|
||||
acc = XXH128_mix32B(acc, input+32, input+len-48, secret+64, seed);
|
||||
}
|
||||
acc = XXH128_mix32B(acc, input+16, input+len-32, secret+32, seed);
|
||||
}
|
||||
acc = XXH128_mix32B(acc, input, input+len-16, secret, seed);
|
||||
|
||||
uint128 h128;
|
||||
h128.low64 = acc.low64 + acc.high64;
|
||||
h128.high64 = (acc.low64 * XXH_PRIME64_1)
|
||||
+ (acc.high64 * XXH_PRIME64_4)
|
||||
+ (((ulong) len - seed) * XXH_PRIME64_2);
|
||||
h128.low64 = XXH3_avalanche(h128.low64);
|
||||
h128.high64 = (ulong) 0 - XXH3_avalanche(h128.high64);
|
||||
return h128;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint128 XXH3_len_9to16_128b(byte* input, int len, byte* secret, ulong seed)
|
||||
{
|
||||
Debug.Assert(input != null);
|
||||
Debug.Assert(secret != null);
|
||||
Debug.Assert(9 <= len && len <= 16);
|
||||
|
||||
ulong bitflipl = (XXH_readLE64(secret + 32) ^ XXH_readLE64(secret + 40)) - seed;
|
||||
ulong bitfliph = (XXH_readLE64(secret + 48) ^ XXH_readLE64(secret + 56)) + seed;
|
||||
ulong input_lo = XXH_readLE64(input);
|
||||
ulong input_hi = XXH_readLE64(input + len - 8);
|
||||
uint128 m128 = XXH_mult64to128(input_lo ^ input_hi ^ bitflipl, XXH_PRIME64_1);
|
||||
|
||||
m128.low64 += (ulong) (len - 1) << 54;
|
||||
input_hi ^= bitfliph;
|
||||
|
||||
m128.high64 += input_hi + XXH_mult32to64((uint) input_hi, XXH_PRIME32_2 - 1);
|
||||
m128.low64 ^= XXH_swap64(m128.high64);
|
||||
|
||||
uint128 h128 = XXH_mult64to128(m128.low64, XXH_PRIME64_2);
|
||||
h128.high64 += m128.high64 * XXH_PRIME64_2;
|
||||
|
||||
h128.low64 = XXH3_avalanche(h128.low64);
|
||||
h128.high64 = XXH3_avalanche(h128.high64);
|
||||
return h128;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint128 XXH3_len_1to3_128b(byte* input, int len, byte* secret, ulong seed)
|
||||
{
|
||||
Debug.Assert(input != null);
|
||||
Debug.Assert(1 <= len && len <= 3);
|
||||
Debug.Assert(secret != null);
|
||||
|
||||
byte c1 = input[0];
|
||||
byte c2 = input[len >> 1];
|
||||
byte c3 = input[len - 1];
|
||||
|
||||
uint combinedl = ((uint) c1 << 16) |
|
||||
((uint) c2 << 24) |
|
||||
((uint) c3 << 0) |
|
||||
((uint) len << 8);
|
||||
uint combinedh = XXH_rotl32(XXH_swap32(combinedl), 13);
|
||||
|
||||
ulong bitflipl = (XXH_readLE32(secret) ^ XXH_readLE32(secret + 4)) + seed;
|
||||
ulong bitfliph = (XXH_readLE32(secret + 8) ^ XXH_readLE32(secret + 12)) - seed;
|
||||
ulong keyed_lo = (ulong) combinedl ^ bitflipl;
|
||||
ulong keyed_hi = (ulong) combinedh ^ bitfliph;
|
||||
|
||||
uint128 h128;
|
||||
h128.low64 = XXH64_avalanche(keyed_lo);
|
||||
h128.high64 = XXH64_avalanche(keyed_hi);
|
||||
|
||||
return h128;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint128 XXH3_len_4to8_128b(byte* input, int len, byte* secret, ulong seed)
|
||||
{
|
||||
Debug.Assert(input != null);
|
||||
Debug.Assert(secret != null);
|
||||
Debug.Assert(4 <= len && len <= 8);
|
||||
|
||||
seed ^= (ulong) XXH_swap32((uint) seed) << 32;
|
||||
|
||||
uint input_lo = XXH_readLE32(input);
|
||||
uint input_hi = XXH_readLE32(input + len - 4);
|
||||
ulong input_64 = input_lo + ((ulong) input_hi << 32);
|
||||
ulong bitflip = (XXH_readLE64(secret + 16) ^ XXH_readLE64(secret + 24)) + seed;
|
||||
ulong keyed = input_64 ^ bitflip;
|
||||
|
||||
uint128 m128 = XXH_mult64to128(keyed, XXH_PRIME64_1 + ((ulong) len << 2));
|
||||
|
||||
m128.high64 += (m128.low64 << 1);
|
||||
m128.low64 ^= (m128.high64 >> 3);
|
||||
|
||||
m128.low64 = XXH_xorshift64(m128.low64, 35);
|
||||
m128.low64 *= 0x9FB21C651E98DF25UL;
|
||||
m128.low64 = XXH_xorshift64(m128.low64, 28);
|
||||
m128.high64 = XXH3_avalanche(m128.high64);
|
||||
|
||||
return m128;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint128 XXH3_len_129to240_128b(byte* input, int len, byte* secret, int secretSize, ulong seed)
|
||||
{
|
||||
Debug.Assert(secretSize >= XXH3_SECRET_SIZE_MIN);
|
||||
Debug.Assert(128 < len && len <= XXH3_MIDSIZE_MAX);
|
||||
|
||||
uint128 acc;
|
||||
int nbRounds = len / 32;
|
||||
|
||||
acc.low64 = (ulong) len * XXH_PRIME64_1;
|
||||
acc.high64 = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
acc = XXH128_mix32B(acc,
|
||||
input + (32 * i),
|
||||
input + (32 * i) + 16,
|
||||
secret + (32 * i),
|
||||
seed);
|
||||
}
|
||||
|
||||
acc.low64 = XXH3_avalanche(acc.low64);
|
||||
acc.high64 = XXH3_avalanche(acc.high64);
|
||||
|
||||
for (int i = 4 ; i < nbRounds; i++) {
|
||||
acc = XXH128_mix32B(acc,
|
||||
input + (32 * i),
|
||||
input + (32 * i) + 16,
|
||||
secret + XXH3_MIDSIZE_STARTOFFSET + (32 * (i - 4)),
|
||||
seed);
|
||||
}
|
||||
|
||||
acc = XXH128_mix32B(acc,
|
||||
input + len - 16,
|
||||
input + len - 32,
|
||||
secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET - 16,
|
||||
0UL - seed);
|
||||
|
||||
uint128 h128;
|
||||
h128.low64 = acc.low64 + acc.high64;
|
||||
h128.high64 = (acc.low64 * XXH_PRIME64_1)
|
||||
+ (acc.high64 * XXH_PRIME64_4)
|
||||
+ (((ulong)len - seed) * XXH_PRIME64_2);
|
||||
h128.low64 = XXH3_avalanche(h128.low64);
|
||||
h128.high64 = (ulong)0 - XXH3_avalanche(h128.high64);
|
||||
return h128;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH3_avalanche(ulong h64)
|
||||
{
|
||||
h64 = XXH_xorshift64(h64, 37);
|
||||
h64 *= 0x165667919E3779F9UL;
|
||||
h64 = XXH_xorshift64(h64, 32);
|
||||
return h64;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint128 XXH128_mix32B(uint128 acc, byte* input_1, byte* input_2, byte* secret, ulong seed)
|
||||
{
|
||||
acc.low64 += XXH3_mix16B(input_1, secret + 0, seed);
|
||||
acc.low64 ^= XXH_readLE64(input_2) + XXH_readLE64(input_2 + 8);
|
||||
acc.high64 += XXH3_mix16B(input_2, secret + 16, seed);
|
||||
acc.high64 ^= XXH_readLE64(input_1) + XXH_readLE64(input_1 + 8);
|
||||
return acc;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH3_mix16B(byte* input, byte* secret, ulong seed)
|
||||
{
|
||||
ulong input_lo = XXH_readLE64(input);
|
||||
ulong input_hi = XXH_readLE64(input + 8);
|
||||
|
||||
return XXH3_mul128_fold64(
|
||||
input_lo ^ (XXH_readLE64(secret) + seed),
|
||||
input_hi ^ (XXH_readLE64(secret + 8) - seed)
|
||||
);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH3_mul128_fold64(ulong lhs, ulong rhs)
|
||||
{
|
||||
uint128 product = XXH_mult64to128(lhs, rhs);
|
||||
return product.low64 ^ product.high64;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint128 XXH3_hashLong_128b_withSeed(byte* input, int len, byte* secret, int secretSize, ulong seed)
|
||||
{
|
||||
if (seed == 0)
|
||||
return XXH3_hashLong_128b_internal(input, len, secret, secretSize);
|
||||
|
||||
byte* customSecret = stackalloc byte[XXH3_SECRET_DEFAULT_SIZE];
|
||||
|
||||
XXH3_initCustomSecret(customSecret, seed);
|
||||
|
||||
return XXH3_hashLong_128b_internal(input, len, customSecret, XXH3_SECRET_DEFAULT_SIZE);
|
||||
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint128 XXH3_hashLong_128b_internal(byte* input, int len, byte* secret, int secretSize)
|
||||
{
|
||||
fixed (ulong* src = &XXH3_INIT_ACC[0])
|
||||
{
|
||||
ulong* acc = stackalloc ulong[8]
|
||||
{
|
||||
*(src + 0),
|
||||
*(src + 1),
|
||||
*(src + 2),
|
||||
*(src + 3),
|
||||
*(src + 4),
|
||||
*(src + 5),
|
||||
*(src + 6),
|
||||
*(src + 7),
|
||||
};
|
||||
|
||||
XXH3_hashLong_internal_loop(acc, input, len, secret, secretSize);
|
||||
|
||||
uint128 uint128;
|
||||
uint128.low64 = XXH3_mergeAccs(acc,
|
||||
secret + XXH_SECRET_MERGEACCS_START,
|
||||
(ulong)len * XXH_PRIME64_1);
|
||||
uint128.high64 = XXH3_mergeAccs(acc,
|
||||
secret + secretSize - XXH3_ACC_SIZE - XXH_SECRET_MERGEACCS_START,
|
||||
~((ulong)len * XXH_PRIME64_2));
|
||||
|
||||
return uint128;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_hashLong_internal_loop(ulong* acc, byte* input, int len, byte* secret, int secretSize)
|
||||
{
|
||||
Debug.Assert(secretSize >= XXH3_SECRET_SIZE_MIN);
|
||||
Debug.Assert(len > XXH_STRIPE_LEN);
|
||||
|
||||
int nbStripesPerBlock = (secretSize - XXH_STRIPE_LEN) / XXH_SECRET_CONSUME_RATE;
|
||||
int block_len = XXH_STRIPE_LEN * nbStripesPerBlock;
|
||||
int nb_blocks = (len - 1) / block_len;
|
||||
|
||||
for (int n = 0; n < nb_blocks; n++) {
|
||||
XXH3_accumulate(acc, input + n * block_len, secret, nbStripesPerBlock);
|
||||
XXH3_scrambleAcc(acc, secret + secretSize - XXH_STRIPE_LEN);
|
||||
}
|
||||
|
||||
int nbStripes = ((len - 1) - (block_len * nb_blocks)) / XXH_STRIPE_LEN;
|
||||
XXH3_accumulate(acc, input + nb_blocks * block_len, secret, nbStripes);
|
||||
|
||||
byte* p = input + len - XXH_STRIPE_LEN;
|
||||
XXH3_accumulate_512(acc, p, secret + secretSize - XXH_STRIPE_LEN - XXH_SECRET_LASTACC_START);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH3_mergeAccs(ulong* acc, byte* secret, ulong start)
|
||||
{
|
||||
ulong result64 = start;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
result64 += XXH3_mix2Accs(acc + 2 * i, secret + 16 * i);
|
||||
|
||||
return XXH3_avalanche(result64);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH3_mix2Accs(ulong* acc, byte* secret)
|
||||
{
|
||||
return XXH3_mul128_fold64(
|
||||
acc[0] ^ XXH_readLE64(secret),
|
||||
acc[1] ^ XXH_readLE64(secret+8) );
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_accumulate(ulong* acc, byte* input, byte* secret, int nbStripes)
|
||||
{
|
||||
for (int n = 0; n < nbStripes; n++ ) {
|
||||
byte* inp = input + n * XXH_STRIPE_LEN;
|
||||
XXH3_accumulate_512(acc, inp, secret + n * XXH_SECRET_CONSUME_RATE);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_accumulate_512(ulong* acc, byte* input, byte* secret)
|
||||
{
|
||||
XXH3_accumulate_512_scalar(acc, input, secret);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_accumulate_512_scalar(ulong* acc, byte* input, byte* secret)
|
||||
{
|
||||
for (int i = 0; i < XXH_ACC_NB; i++)
|
||||
XXH3_scalarRound(acc, input, secret, i);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_scalarRound(ulong* acc, byte* input, byte* secret, int lane)
|
||||
{
|
||||
Debug.Assert(lane < XXH_ACC_NB);
|
||||
|
||||
ulong* xacc = acc;
|
||||
byte* xinput = input;
|
||||
byte* xsecret = secret;
|
||||
|
||||
ulong data_val = XXH_readLE64(xinput + lane * 8);
|
||||
ulong data_key = data_val ^ XXH_readLE64(xsecret + lane * 8);
|
||||
xacc[lane ^ 1] += data_val;
|
||||
xacc[lane] += XXH_mult32to64(data_key & 0xFFFFFFFF, data_key >> 32);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_scrambleAcc(ulong* acc, byte* secret)
|
||||
{
|
||||
XXH3_scrambleAcc_scalar(acc, secret);
|
||||
}
|
||||
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_scrambleAcc_scalar(ulong* acc, byte* secret)
|
||||
{
|
||||
for (int i = 0; i < XXH_ACC_NB; i++)
|
||||
XXH3_scalarScrambleRound(acc, secret, i);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_scalarScrambleRound(ulong* acc, byte* secret, int lane)
|
||||
{
|
||||
Debug.Assert(lane < XXH_ACC_NB);
|
||||
|
||||
ulong* xacc = acc;
|
||||
byte* xsecret = secret;
|
||||
|
||||
ulong key64 = XXH_readLE64(xsecret + lane * 8);
|
||||
ulong acc64 = xacc[lane];
|
||||
acc64 = XXH_xorshift64(acc64, 47);
|
||||
acc64 ^= key64;
|
||||
acc64 *= XXH_PRIME32_1;
|
||||
xacc[lane] = acc64;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_initCustomSecret(byte* customSecret, ulong seed)
|
||||
{
|
||||
XXH3_initCustomSecret_scalar(customSecret, seed);
|
||||
}
|
||||
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_initCustomSecret_scalar(byte* customSecret, ulong seed)
|
||||
{
|
||||
fixed (byte* kSecretPtr = &XXH3_SECRET[0])
|
||||
{
|
||||
int nbRounds = XXH_SECRET_DEFAULT_SIZE / 16;
|
||||
|
||||
for (int i = 0; i < nbRounds; i++)
|
||||
{
|
||||
ulong lo = XXH_readLE64(kSecretPtr + 16 * i) + seed;
|
||||
ulong hi = XXH_readLE64(kSecretPtr + 16 * i + 8) - seed;
|
||||
XXH_writeLE64((byte*) customSecret + 16 * i, lo);
|
||||
XXH_writeLE64((byte*) customSecret + 16 * i + 8, hi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1df288f95a653c44dbd9a60f9d9c8979
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,20 @@
|
|||
// ReSharper disable InconsistentNaming
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
public static partial class xxHash128
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH64_avalanche(ulong hash)
|
||||
{
|
||||
hash ^= hash >> 33;
|
||||
hash *= XXH_PRIME64_2;
|
||||
hash ^= hash >> 29;
|
||||
hash *= XXH_PRIME64_3;
|
||||
hash ^= hash >> 32;
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 47b4bf89c9a50a845808824ae5a4b295
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,180 @@
|
|||
// ReSharper disable InconsistentNaming
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
public static partial class xxHash128
|
||||
{
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte array
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe uint128 ComputeHash(byte[] data, int length, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* ptr = &data[0])
|
||||
{
|
||||
return UnsafeComputeHash(ptr, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte span
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe uint128 ComputeHash(Span<byte> data, int length, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* ptr = &data[0])
|
||||
{
|
||||
return UnsafeComputeHash(ptr, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte span
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe uint128 ComputeHash(ReadOnlySpan<byte> data, int length, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* ptr = &data[0])
|
||||
{
|
||||
return UnsafeComputeHash(ptr, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the string
|
||||
/// </summary>
|
||||
/// <param name="str">The source of data</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe uint128 ComputeHash(string str, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(str != null);
|
||||
|
||||
fixed (char* c = str)
|
||||
{
|
||||
byte* ptr = (byte*) c;
|
||||
int length = str.Length * 2;
|
||||
|
||||
return UnsafeComputeHash(ptr, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute hash bytes for the data byte array
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe byte[] ComputeHashBytes(byte[] data, int length, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* ptr = &data[0])
|
||||
{
|
||||
return UnsafeComputeHash(ptr, length, seed).ToBytes();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute hash bytes for the span
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe byte[] ComputeHashBytes(Span<byte> data, int length, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* ptr = &data[0])
|
||||
{
|
||||
return UnsafeComputeHash(ptr, length, seed).ToBytes();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute hash bytes for the data byte span
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe byte[] ComputeHashBytes(ReadOnlySpan<byte> data, int length, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* ptr = &data[0])
|
||||
{
|
||||
return UnsafeComputeHash(ptr, length, seed).ToBytes();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute hash bytes for the string
|
||||
/// </summary>
|
||||
/// <param name="str">The source of data</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe byte[] ComputeHashBytes(string str, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(str != null);
|
||||
|
||||
fixed (char* c = str)
|
||||
{
|
||||
byte* ptr = (byte*) c;
|
||||
int length = str.Length * 2;
|
||||
|
||||
return UnsafeComputeHash(ptr, length, seed).ToBytes();
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint128 UnsafeComputeHash(byte* input, int len, ulong seed)
|
||||
{
|
||||
fixed (byte* secret = &XXH3_SECRET[0])
|
||||
{
|
||||
return XXH3_128bits_internal(input, len, seed, secret, XXH3_SECRET_DEFAULT_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct uint128
|
||||
{
|
||||
public ulong low64;
|
||||
public ulong high64;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1ea51d2884ca3b94baf4305ff37b0fcb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,118 @@
|
|||
// ReSharper disable InconsistentNaming
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
public static partial class xxHash3
|
||||
{
|
||||
private static readonly ulong XXH_PRIME64_1 = 11400714785074694791UL;
|
||||
private static readonly ulong XXH_PRIME64_2 = 14029467366897019727UL;
|
||||
private static readonly ulong XXH_PRIME64_3 = 1609587929392839161UL;
|
||||
private static readonly ulong XXH_PRIME64_4 = 9650029242287828579UL;
|
||||
private static readonly ulong XXH_PRIME64_5 = 2870177450012600261UL;
|
||||
|
||||
private static readonly uint XXH_PRIME32_1 = 2654435761U;
|
||||
private static readonly uint XXH_PRIME32_2 = 2246822519U;
|
||||
private static readonly uint XXH_PRIME32_3 = 3266489917U;
|
||||
private static readonly uint XXH_PRIME32_4 = 668265263U;
|
||||
private static readonly uint XXH_PRIME32_5 = 374761393U;
|
||||
|
||||
private static readonly int XXH_STRIPE_LEN = 64;
|
||||
private static readonly int XXH_ACC_NB = XXH_STRIPE_LEN / 8;
|
||||
private static readonly int XXH_SECRET_CONSUME_RATE = 8;
|
||||
private static readonly int XXH_SECRET_DEFAULT_SIZE = 192;
|
||||
private static readonly int XXH_SECRET_MERGEACCS_START = 11;
|
||||
private static readonly int XXH_SECRET_LASTACC_START = 7;
|
||||
|
||||
private static readonly byte MM_SHUFFLE_0_3_0_1 = 0b0011_0001;
|
||||
private static readonly byte MM_SHUFFLE_1_0_3_2 = 0b0100_1110;
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH_readLE64(byte* ptr)
|
||||
{
|
||||
return *(ulong*) ptr;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint XXH_readLE32(byte* ptr)
|
||||
{
|
||||
return *(uint*) ptr;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH_swap64(ulong x)
|
||||
{
|
||||
return ((x << 56) & 0xff00000000000000UL) |
|
||||
((x << 40) & 0x00ff000000000000UL) |
|
||||
((x << 24) & 0x0000ff0000000000UL) |
|
||||
((x << 8) & 0x000000ff00000000UL) |
|
||||
((x >> 8) & 0x00000000ff000000UL) |
|
||||
((x >> 24) & 0x0000000000ff0000UL) |
|
||||
((x >> 40) & 0x000000000000ff00UL) |
|
||||
((x >> 56) & 0x00000000000000ffUL);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH_mult32to64(ulong x, ulong y)
|
||||
{
|
||||
return (ulong) (uint) (x) * (ulong) (uint) (y);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH_xorshift64(ulong v64, int shift)
|
||||
{
|
||||
return v64 ^ (v64 >> shift);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static uint XXH_swap32(uint x)
|
||||
{
|
||||
return ((x << 24) & 0xff000000) |
|
||||
((x << 8) & 0x00ff0000) |
|
||||
((x >> 8) & 0x0000ff00) |
|
||||
((x >> 24) & 0x000000ff);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH_rotl64(ulong x, int r)
|
||||
{
|
||||
return (x << r) | (x >> (64 - r));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH_writeLE64(byte* dst, ulong v64)
|
||||
{
|
||||
*(ulong*) dst = v64;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static uint128 XXH_mult64to128(ulong lhs, ulong rhs)
|
||||
{
|
||||
|
||||
|
||||
return XXH_mult64to128_scalar(lhs, rhs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static uint128 XXH_mult64to128_scalar(ulong lhs, ulong rhs)
|
||||
{
|
||||
ulong lo_lo = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs & 0xFFFFFFFF);
|
||||
ulong hi_lo = XXH_mult32to64(lhs >> 32, rhs & 0xFFFFFFFF);
|
||||
ulong lo_hi = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs >> 32);
|
||||
ulong hi_hi = XXH_mult32to64(lhs >> 32, rhs >> 32);
|
||||
|
||||
ulong cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi;
|
||||
ulong upper = (hi_lo >> 32) + (cross >> 32) + hi_hi;
|
||||
ulong lower = (cross << 32) | (lo_lo & 0xFFFFFFFF);
|
||||
|
||||
uint128 r128;
|
||||
r128.low64 = lower;
|
||||
r128.high64 = upper;
|
||||
return r128;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 93e944ab70a22e948a6bc0ef5de471c3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,368 @@
|
|||
// ReSharper disable InconsistentNaming
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
public static partial class xxHash3
|
||||
{
|
||||
private static readonly byte[] XXH3_SECRET =
|
||||
{
|
||||
0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,
|
||||
0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,
|
||||
0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21,
|
||||
0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c,
|
||||
0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3,
|
||||
0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8,
|
||||
0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d,
|
||||
0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64,
|
||||
0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb,
|
||||
0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e,
|
||||
0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce,
|
||||
0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,
|
||||
};
|
||||
|
||||
private static readonly ulong[] XXH3_INIT_ACC =
|
||||
{
|
||||
XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3,
|
||||
XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1
|
||||
};
|
||||
|
||||
private static readonly int XXH3_MIDSIZE_MAX = 240;
|
||||
private static readonly int XXH3_MIDSIZE_STARTOFFSET = 3;
|
||||
private static readonly int XXH3_MIDSIZE_LASTOFFSET = 17;
|
||||
private static readonly int XXH3_SECRET_SIZE_MIN = 136;
|
||||
private static readonly int XXH3_SECRET_DEFAULT_SIZE = 192;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH3_64bits_internal(byte* input, int len, ulong seed64, byte* secret,
|
||||
int secretLen)
|
||||
{
|
||||
if (len <= 16)
|
||||
return XXH3_len_0to16_64b(input, len, secret, seed64);
|
||||
if (len <= 128)
|
||||
return XXH3_len_17to128_64b(input, len, secret, secretLen, seed64);
|
||||
if (len <= XXH3_MIDSIZE_MAX)
|
||||
return XXH3_len_129to240_64b(input, len, secret, secretLen, seed64);
|
||||
|
||||
return XXH3_hashLong_64b_withSeed(input, len, seed64, secret, secretLen);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH3_len_0to16_64b(byte* input, int len, byte* secret, ulong seed)
|
||||
{
|
||||
if (len > 8)
|
||||
return XXH3_len_9to16_64b(input, len, secret, seed);
|
||||
if (len >= 4)
|
||||
return XXH3_len_4to8_64b(input, len, secret, seed);
|
||||
if (len != 0)
|
||||
return XXH3_len_1to3_64b(input, len, secret, seed);
|
||||
|
||||
return XXH64_avalanche(seed ^ (XXH_readLE64(secret + 56) ^ XXH_readLE64(secret + 64)));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH3_len_9to16_64b(byte* input, int len, byte* secret, ulong seed)
|
||||
{
|
||||
ulong bitflip1 = (XXH_readLE64(secret + 24) ^ XXH_readLE64(secret + 32)) + seed;
|
||||
ulong bitflip2 = (XXH_readLE64(secret + 40) ^ XXH_readLE64(secret + 48)) - seed;
|
||||
ulong input_lo = XXH_readLE64(input) ^ bitflip1;
|
||||
ulong input_hi = XXH_readLE64(input + len - 8) ^ bitflip2;
|
||||
ulong acc = ((ulong) len)
|
||||
+ XXH_swap64(input_lo) + input_hi
|
||||
+ XXH3_mul128_fold64(input_lo, input_hi);
|
||||
return XXH3_avalanche(acc);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH3_mul128_fold64(ulong lhs, ulong rhs)
|
||||
{
|
||||
uint128 product = XXH_mult64to128(lhs, rhs);
|
||||
return product.low64 ^ product.high64;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH3_avalanche(ulong h64)
|
||||
{
|
||||
h64 = XXH_xorshift64(h64, 37);
|
||||
h64 *= 0x165667919E3779F9UL;
|
||||
h64 = XXH_xorshift64(h64, 32);
|
||||
return h64;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH3_len_4to8_64b(byte* input, int len, byte* secret, ulong seed)
|
||||
{
|
||||
seed ^= (ulong) XXH_swap32((uint) seed) << 32;
|
||||
{
|
||||
uint input1 = XXH_readLE32(input);
|
||||
uint input2 = XXH_readLE32(input + len - 4);
|
||||
ulong bitflip = (XXH_readLE64(secret + 8) ^ XXH_readLE64(secret + 16)) - seed;
|
||||
ulong input64 = input2 + (((ulong) input1) << 32);
|
||||
ulong keyed = input64 ^ bitflip;
|
||||
return XXH3_rrmxmx(keyed, len);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH3_rrmxmx(ulong h64, int len)
|
||||
{
|
||||
h64 ^= XXH_rotl64(h64, 49) ^ XXH_rotl64(h64, 24);
|
||||
h64 *= 0x9FB21C651E98DF25UL;
|
||||
h64 ^= (h64 >> 35) + (ulong) len;
|
||||
h64 *= 0x9FB21C651E98DF25UL;
|
||||
return XXH_xorshift64(h64, 28);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH3_len_1to3_64b(byte* input, int len, byte* secret, ulong seed)
|
||||
{
|
||||
byte c1 = input[0];
|
||||
byte c2 = input[len >> 1];
|
||||
byte c3 = input[len - 1];
|
||||
uint combined = ((uint) c1 << 16) |
|
||||
((uint) c2 << 24) |
|
||||
((uint) c3 << 0) |
|
||||
((uint) len << 8);
|
||||
|
||||
ulong bitflip = (XXH_readLE32(secret) ^
|
||||
XXH_readLE32(secret + 4)) + seed;
|
||||
|
||||
ulong keyed = (ulong)combined ^ bitflip;
|
||||
return XXH64_avalanche(keyed);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH3_len_17to128_64b(byte* input, int len, byte* secret, int secretSize, ulong seed)
|
||||
{
|
||||
ulong acc = ((ulong)len) * XXH_PRIME64_1;
|
||||
|
||||
if (len > 32)
|
||||
{
|
||||
if (len > 64)
|
||||
{
|
||||
if (len > 96)
|
||||
{
|
||||
acc += XXH3_mix16B(input + 48, secret + 96, seed);
|
||||
acc += XXH3_mix16B(input + len - 64, secret + 112, seed);
|
||||
}
|
||||
acc += XXH3_mix16B(input + 32, secret + 64, seed);
|
||||
acc += XXH3_mix16B(input + len - 48, secret + 80, seed);
|
||||
}
|
||||
acc += XXH3_mix16B(input + 16, secret + 32, seed);
|
||||
acc += XXH3_mix16B(input + len - 32, secret + 48, seed);
|
||||
}
|
||||
|
||||
acc += XXH3_mix16B(input + 0, secret + 0, seed);
|
||||
acc += XXH3_mix16B(input + len - 16, secret + 16, seed);
|
||||
return XXH3_avalanche(acc);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH3_mix16B(byte* input, byte* secret, ulong seed64)
|
||||
{
|
||||
ulong input_lo = XXH_readLE64(input);
|
||||
ulong input_hi = XXH_readLE64(input + 8);
|
||||
|
||||
return XXH3_mul128_fold64(
|
||||
input_lo ^ (XXH_readLE64(secret) + seed64),
|
||||
input_hi ^ (XXH_readLE64(secret + 8) - seed64)
|
||||
);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH3_len_129to240_64b(byte* input, int len, byte* secret, int secretSize,
|
||||
ulong seed)
|
||||
{
|
||||
ulong acc = ((ulong) len) * XXH_PRIME64_1;
|
||||
int nbRounds = len / 16;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
acc += XXH3_mix16B(input + (16 * i), secret + (16 * i), seed);
|
||||
}
|
||||
acc = XXH3_avalanche(acc);
|
||||
|
||||
for (int i = 8; i < nbRounds; i++)
|
||||
{
|
||||
acc += XXH3_mix16B(input + (16 * i), secret + (16 * (i - 8)) + XXH3_MIDSIZE_STARTOFFSET, seed);
|
||||
}
|
||||
|
||||
acc += XXH3_mix16B(input + len - 16, secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET, seed);
|
||||
return XXH3_avalanche(acc);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH3_hashLong_64b_withSeed(byte* input, int len, ulong seed, byte* secret,
|
||||
int secretSize)
|
||||
{
|
||||
if (seed == 0)
|
||||
return XXH3_hashLong_64b_internal(input, len, secret, secretSize);
|
||||
|
||||
byte* customSecret = stackalloc byte[XXH3_SECRET_DEFAULT_SIZE];
|
||||
|
||||
XXH3_initCustomSecret(customSecret, seed);
|
||||
|
||||
return XXH3_hashLong_64b_internal(input, len, customSecret, XXH3_SECRET_DEFAULT_SIZE);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_initCustomSecret(byte* customSecret, ulong seed)
|
||||
{
|
||||
XXH3_initCustomSecret_scalar(customSecret, seed);
|
||||
}
|
||||
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_initCustomSecret_scalar(byte* customSecret, ulong seed)
|
||||
{
|
||||
fixed (byte* kSecretPtr = &XXH3_SECRET[0])
|
||||
{
|
||||
int nbRounds = XXH_SECRET_DEFAULT_SIZE / 16;
|
||||
|
||||
for (int i = 0; i < nbRounds; i++)
|
||||
{
|
||||
ulong lo = XXH_readLE64(kSecretPtr + 16 * i) + seed;
|
||||
ulong hi = XXH_readLE64(kSecretPtr + 16 * i + 8) - seed;
|
||||
XXH_writeLE64((byte*) customSecret + 16 * i, lo);
|
||||
XXH_writeLE64((byte*) customSecret + 16 * i + 8, hi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH3_hashLong_64b_internal(byte* input, int len, byte* secret, int secretSize)
|
||||
{
|
||||
fixed (ulong* src = &XXH3_INIT_ACC[0])
|
||||
{
|
||||
ulong* acc = stackalloc ulong[8]
|
||||
{
|
||||
*(src + 0),
|
||||
*(src + 1),
|
||||
*(src + 2),
|
||||
*(src + 3),
|
||||
*(src + 4),
|
||||
*(src + 5),
|
||||
*(src + 6),
|
||||
*(src + 7),
|
||||
};
|
||||
|
||||
XXH3_hashLong_internal_loop(acc, input, len, secret, secretSize);
|
||||
|
||||
return XXH3_mergeAccs(acc, secret + XXH_SECRET_MERGEACCS_START, ((ulong)len) * XXH_PRIME64_1);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH3_mergeAccs(ulong* acc, byte* secret, ulong start)
|
||||
{
|
||||
ulong result64 = start;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
result64 += XXH3_mix2Accs(acc + 2 * i, secret + 16 * i);
|
||||
|
||||
return XXH3_avalanche(result64);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH3_mix2Accs(ulong* acc, byte* secret)
|
||||
{
|
||||
return XXH3_mul128_fold64(
|
||||
acc[0] ^ XXH_readLE64(secret),
|
||||
acc[1] ^ XXH_readLE64(secret + 8));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_hashLong_internal_loop(ulong* acc, byte* input, int len, byte* secret,
|
||||
int secretSize)
|
||||
{
|
||||
int nbStripesPerBlock = (secretSize - XXH_STRIPE_LEN) / XXH_SECRET_CONSUME_RATE;
|
||||
int block_len = XXH_STRIPE_LEN * nbStripesPerBlock;
|
||||
int nb_blocks = (len - 1) / block_len;
|
||||
|
||||
for (int n = 0; n < nb_blocks; n++)
|
||||
{
|
||||
XXH3_accumulate(acc, input + n * block_len, secret, nbStripesPerBlock);
|
||||
XXH3_scrambleAcc(acc, secret + secretSize - XXH_STRIPE_LEN);
|
||||
}
|
||||
|
||||
int nbStripes = ((len - 1) - (block_len * nb_blocks)) / XXH_STRIPE_LEN;
|
||||
XXH3_accumulate(acc, input + nb_blocks * block_len, secret, nbStripes);
|
||||
|
||||
byte* p = input + len - XXH_STRIPE_LEN;
|
||||
XXH3_accumulate_512(acc, p, secret + secretSize - XXH_STRIPE_LEN - XXH_SECRET_LASTACC_START);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_accumulate(ulong* acc, byte* input, byte* secret, int nbStripes)
|
||||
{
|
||||
for (int n = 0; n < nbStripes; n++)
|
||||
{
|
||||
byte* inp = input + n * XXH_STRIPE_LEN;
|
||||
XXH3_accumulate_512(acc, inp, secret + n * XXH_SECRET_CONSUME_RATE);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_accumulate_512(ulong* acc, byte* input, byte* secret)
|
||||
{
|
||||
XXH3_accumulate_512_scalar(acc, input, secret);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_accumulate_512_scalar(ulong* acc, byte* input, byte* secret)
|
||||
{
|
||||
for (int i = 0; i < XXH_ACC_NB; i++)
|
||||
XXH3_scalarRound(acc, input, secret, i);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_scalarRound(ulong* acc, byte* input, byte* secret, int lane)
|
||||
{
|
||||
ulong* xacc = acc;
|
||||
byte* xinput = input;
|
||||
byte* xsecret = secret;
|
||||
|
||||
ulong data_val = XXH_readLE64(xinput + lane * 8);
|
||||
ulong data_key = data_val ^ XXH_readLE64(xsecret + lane * 8);
|
||||
xacc[lane ^ 1] += data_val;
|
||||
xacc[lane] += XXH_mult32to64(data_key & 0xFFFFFFFF, data_key >> 32);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_scrambleAcc(ulong* acc, byte* secret)
|
||||
{
|
||||
XXH3_scrambleAcc_scalar(acc, secret);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_scrambleAcc_scalar(ulong* acc, byte* secret)
|
||||
{
|
||||
for (int i = 0; i < XXH_ACC_NB; i++)
|
||||
XXH3_scalarScrambleRound(acc, secret, i);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void XXH3_scalarScrambleRound(ulong* acc, byte* secret, int lane)
|
||||
{
|
||||
ulong* xacc = acc;
|
||||
byte* xsecret = secret;
|
||||
|
||||
ulong key64 = XXH_readLE64(xsecret + lane * 8);
|
||||
ulong acc64 = xacc[lane];
|
||||
acc64 = XXH_xorshift64(acc64, 47);
|
||||
acc64 ^= key64;
|
||||
acc64 *= XXH_PRIME32_1;
|
||||
xacc[lane] = acc64;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 04c10c3dcad63224fab3244c585bc4e4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,20 @@
|
|||
// ReSharper disable InconsistentNaming
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
public static partial class xxHash3
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH64_avalanche(ulong hash)
|
||||
{
|
||||
hash ^= hash >> 33;
|
||||
hash *= XXH_PRIME64_2;
|
||||
hash ^= hash >> 29;
|
||||
hash *= XXH_PRIME64_3;
|
||||
hash ^= hash >> 32;
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6b73a0fcfb28bb44b8d7ce7bb03436a0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,96 @@
|
|||
// ReSharper disable InconsistentNaming
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
public static partial class xxHash3
|
||||
{
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte array
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe ulong ComputeHash(byte[] data, int length, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* ptr = &data[0])
|
||||
{
|
||||
return UnsafeComputeHash(ptr, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte span
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe ulong ComputeHash(Span<byte> data, int length, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* ptr = &data[0])
|
||||
{
|
||||
return UnsafeComputeHash(ptr, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte span
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe ulong ComputeHash(ReadOnlySpan<byte> data, int length, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* ptr = &data[0])
|
||||
{
|
||||
return UnsafeComputeHash(ptr, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the string
|
||||
/// </summary>
|
||||
/// <param name="unicode">The source of data</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe ulong ComputeHash(string unicode, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(unicode != null);
|
||||
|
||||
fixed (char* c = unicode)
|
||||
{
|
||||
byte* ptr = (byte*) c;
|
||||
int length = unicode.Length * 2;
|
||||
|
||||
return UnsafeComputeHash(ptr, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong UnsafeComputeHash(byte* input, int len, ulong seed)
|
||||
{
|
||||
fixed (byte* secret = &XXH3_SECRET[0])
|
||||
{
|
||||
return XXH3_64bits_internal(input, len, seed, secret, XXH3_SECRET_DEFAULT_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a61e53921f712184a91693b7937b53fb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,21 @@
|
|||
// ReSharper disable InconsistentNaming
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
public static partial class xxHash32
|
||||
{
|
||||
private static readonly uint XXH_PRIME32_1 = 2654435761U;
|
||||
private static readonly uint XXH_PRIME32_2 = 2246822519U;
|
||||
private static readonly uint XXH_PRIME32_3 = 3266489917U;
|
||||
private static readonly uint XXH_PRIME32_4 = 668265263U;
|
||||
private static readonly uint XXH_PRIME32_5 = 374761393U;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static uint XXH_rotl32(uint x, int r)
|
||||
{
|
||||
return (x << r) | (x >> (32 - r));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1c5bf48410ae0d74f8803b0b407b8af5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,90 @@
|
|||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
public static partial class xxHash32
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint XXH32(byte* input, int len, uint seed)
|
||||
{
|
||||
uint h32;
|
||||
|
||||
if (len >= 16)
|
||||
{
|
||||
byte* end = input + len;
|
||||
byte* limit = end - 15;
|
||||
|
||||
uint v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2;
|
||||
uint v2 = seed + XXH_PRIME32_2;
|
||||
uint v3 = seed + 0;
|
||||
uint v4 = seed - XXH_PRIME32_1;
|
||||
|
||||
do
|
||||
{
|
||||
v1 = XXH32_round(v1, *(uint*) input); input += 4;
|
||||
v2 = XXH32_round(v2, *(uint*) input); input += 4;
|
||||
v3 = XXH32_round(v3, *(uint*) input); input += 4;
|
||||
v4 = XXH32_round(v4, *(uint*) input); input += 4;
|
||||
} while (input < limit);
|
||||
|
||||
h32 = XXH_rotl32(v1, 1) +
|
||||
XXH_rotl32(v2, 7) +
|
||||
XXH_rotl32(v3, 12) +
|
||||
XXH_rotl32(v4, 18);
|
||||
}
|
||||
else
|
||||
{
|
||||
h32 = seed + XXH_PRIME32_5;
|
||||
}
|
||||
|
||||
h32 += (uint)len;
|
||||
|
||||
return XXH32_finalize(h32, input, len);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static uint XXH32_round(uint acc, uint input)
|
||||
{
|
||||
acc += input * XXH_PRIME32_2;
|
||||
acc = XXH_rotl32(acc, 13);
|
||||
acc *= XXH_PRIME32_1;
|
||||
return acc;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static uint XXH32_avalanche(uint hash)
|
||||
{
|
||||
hash ^= hash >> 15;
|
||||
hash *= XXH_PRIME32_2;
|
||||
hash ^= hash >> 13;
|
||||
hash *= XXH_PRIME32_3;
|
||||
hash ^= hash >> 16;
|
||||
return hash;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint XXH32_finalize(uint hash, byte* ptr, int len)
|
||||
{
|
||||
len &= 15;
|
||||
while (len >= 4)
|
||||
{
|
||||
hash += *((uint*)ptr) * XXH_PRIME32_3;
|
||||
ptr += 4;
|
||||
hash = XXH_rotl32(hash, 17) * XXH_PRIME32_4;
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
hash += *((byte*)ptr) * XXH_PRIME32_5;
|
||||
ptr++;
|
||||
hash = XXH_rotl32(hash, 11) * XXH_PRIME32_1;
|
||||
len--;
|
||||
}
|
||||
|
||||
return XXH32_avalanche(hash);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 72917bf63cde5cb4a83abbbf562a684a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,265 @@
|
|||
// ReSharper disable InconsistentNaming
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
public static partial class xxHash32
|
||||
{
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte array
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe uint ComputeHash(byte[] data, int length, uint seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* pData = &data[0])
|
||||
{
|
||||
return UnsafeComputeHash(pData, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte array
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="offset">The offset of the data for hashing</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe uint ComputeHash(byte[] data, int offset, int length, uint seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(offset < data.Length);
|
||||
Debug.Assert(length <= data.Length - offset);
|
||||
|
||||
fixed (byte* pData = &data[0 + offset])
|
||||
{
|
||||
return UnsafeComputeHash(pData, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte array
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static ulong ComputeHash(ArraySegment<byte> data, uint seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
|
||||
return ComputeHash(data.Array, data.Offset, data.Count, seed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the async stream
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream of data</param>
|
||||
/// <param name="bufferSize">The buffer size</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>The hash</returns>
|
||||
public static async ValueTask<uint> ComputeHashAsync(Stream stream, int bufferSize = 4096, uint seed = 0)
|
||||
{
|
||||
return await ComputeHashAsync(stream, bufferSize, seed, CancellationToken.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the async stream
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream of data</param>
|
||||
/// <param name="bufferSize">The buffer size</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <param name="cancellationToken">The cancellation token</param>
|
||||
/// <returns>The hash</returns>
|
||||
public static async ValueTask<uint> ComputeHashAsync(Stream stream, int bufferSize, uint seed, CancellationToken cancellationToken)
|
||||
{
|
||||
Debug.Assert(stream != null);
|
||||
Debug.Assert(bufferSize > 16);
|
||||
|
||||
// Optimizing memory allocation
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize + 16);
|
||||
|
||||
int readBytes;
|
||||
int offset = 0;
|
||||
long length = 0;
|
||||
|
||||
// Prepare the seed vector
|
||||
uint v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2;
|
||||
uint v2 = seed + XXH_PRIME32_2;
|
||||
uint v3 = seed + 0;
|
||||
uint v4 = seed - XXH_PRIME32_1;
|
||||
|
||||
try
|
||||
{
|
||||
// Read flow of bytes
|
||||
while ((readBytes =
|
||||
await stream.ReadAsync(buffer, offset, bufferSize, cancellationToken).ConfigureAwait(false)) > 0)
|
||||
{
|
||||
length = length + readBytes;
|
||||
offset = offset + readBytes;
|
||||
|
||||
if (offset < 16) continue;
|
||||
|
||||
int r = offset % 16; // remain
|
||||
int l = offset - r; // length
|
||||
|
||||
// Process the next chunk
|
||||
__inline__XXH32_stream_process(buffer, l, ref v1, ref v2, ref v3, ref v4);
|
||||
|
||||
// Put remaining bytes to buffer
|
||||
Utils.BlockCopy(buffer, l, buffer, 0, r);
|
||||
offset = r;
|
||||
}
|
||||
|
||||
// Process the final chunk
|
||||
uint h32 = __inline__XXH32_stream_finalize(buffer, offset, ref v1, ref v2, ref v3, ref v4, length, seed);
|
||||
|
||||
return h32;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Free memory
|
||||
ArrayPool<byte>.Shared.Return(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte span
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe uint ComputeHash(Span<byte> data, int length, uint seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* pData = &MemoryMarshal.GetReference(data))
|
||||
{
|
||||
return UnsafeComputeHash(pData, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte span
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe uint ComputeHash(ReadOnlySpan<byte> data, int length, uint seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* pData = &MemoryMarshal.GetReference(data))
|
||||
{
|
||||
return UnsafeComputeHash(pData, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the stream
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream of data</param>
|
||||
/// <param name="bufferSize">The buffer size</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>The hash</returns>
|
||||
public static uint ComputeHash(Stream stream, int bufferSize = 4096, uint seed = 0)
|
||||
{
|
||||
Debug.Assert(stream != null);
|
||||
Debug.Assert(bufferSize > 16);
|
||||
|
||||
// Optimizing memory allocation
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize + 16);
|
||||
|
||||
int readBytes;
|
||||
int offset = 0;
|
||||
long length = 0;
|
||||
|
||||
// Prepare the seed vector
|
||||
uint v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2;
|
||||
uint v2 = seed + XXH_PRIME32_2;
|
||||
uint v3 = seed + 0;
|
||||
uint v4 = seed - XXH_PRIME32_1;
|
||||
|
||||
try
|
||||
{
|
||||
// Read flow of bytes
|
||||
while ((readBytes = stream.Read(buffer, offset, bufferSize)) > 0)
|
||||
{
|
||||
length = length + readBytes;
|
||||
offset = offset + readBytes;
|
||||
|
||||
if (offset < 16) continue;
|
||||
|
||||
int r = offset % 16; // remain
|
||||
int l = offset - r; // length
|
||||
|
||||
// Process the next chunk
|
||||
__inline__XXH32_stream_process(buffer, l, ref v1, ref v2, ref v3, ref v4);
|
||||
|
||||
// Put remaining bytes to buffer
|
||||
Utils.BlockCopy(buffer, l, buffer, 0, r);
|
||||
offset = r;
|
||||
}
|
||||
|
||||
// Process the last chunk
|
||||
uint h32 = __inline__XXH32_stream_finalize(buffer, offset, ref v1, ref v2, ref v3, ref v4, length, seed);
|
||||
|
||||
return h32;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Free memory
|
||||
ArrayPool<byte>.Shared.Return(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the string
|
||||
/// </summary>
|
||||
/// <param name="str">The source of data</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe uint ComputeHash(string str, uint seed = 0)
|
||||
{
|
||||
Debug.Assert(str != null);
|
||||
|
||||
fixed (char* c = str)
|
||||
{
|
||||
byte* ptr = (byte*) c;
|
||||
int length = str.Length * 2;
|
||||
|
||||
return UnsafeComputeHash(ptr, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe uint UnsafeComputeHash(byte* ptr, int length, uint seed)
|
||||
{
|
||||
// Use inlined version
|
||||
// return XXH32(ptr, length, seed);
|
||||
|
||||
return __inline__XXH32(ptr, length, seed);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 877a8f61386aaf044bb5b0876d759d3e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,21 @@
|
|||
// ReSharper disable InconsistentNaming
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
public static partial class xxHash64
|
||||
{
|
||||
private static readonly ulong XXH_PRIME64_1 = 11400714785074694791UL;
|
||||
private static readonly ulong XXH_PRIME64_2 = 14029467366897019727UL;
|
||||
private static readonly ulong XXH_PRIME64_3 = 1609587929392839161UL;
|
||||
private static readonly ulong XXH_PRIME64_4 = 9650029242287828579UL;
|
||||
private static readonly ulong XXH_PRIME64_5 = 2870177450012600261UL;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH_rotl64(ulong x, int r)
|
||||
{
|
||||
return (x << r) | (x >> (64 - r));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 519eafbf3455e3c4e8a3cee3051367ad
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,106 @@
|
|||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
public static partial class xxHash64
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH64(byte* input, int len, ulong seed)
|
||||
{
|
||||
ulong h64;
|
||||
|
||||
if (len >= 32)
|
||||
{
|
||||
byte* end = input + len;
|
||||
byte* limit = end - 31;
|
||||
|
||||
ulong v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2;
|
||||
ulong v2 = seed + XXH_PRIME64_2;
|
||||
ulong v3 = seed + 0;
|
||||
ulong v4 = seed - XXH_PRIME64_1;
|
||||
|
||||
do
|
||||
{
|
||||
v1 = XXH64_round(v1, *(ulong*) input); input += 8;
|
||||
v2 = XXH64_round(v2, *(ulong*) input); input += 8;
|
||||
v3 = XXH64_round(v3, *(ulong*) input); input += 8;
|
||||
v4 = XXH64_round(v4, *(ulong*) input); input += 8;
|
||||
} while (input < limit);
|
||||
|
||||
h64 = XXH_rotl64(v1, 1) +
|
||||
XXH_rotl64(v2, 7) +
|
||||
XXH_rotl64(v3, 12) +
|
||||
XXH_rotl64(v4, 18);
|
||||
|
||||
h64 = XXH64_mergeRound(h64, v1);
|
||||
h64 = XXH64_mergeRound(h64, v2);
|
||||
h64 = XXH64_mergeRound(h64, v3);
|
||||
h64 = XXH64_mergeRound(h64, v4);
|
||||
}
|
||||
else
|
||||
{
|
||||
h64 = seed + XXH_PRIME64_5;
|
||||
}
|
||||
|
||||
h64 += (ulong)len;
|
||||
|
||||
return XXH64_finalize(h64, input, len);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH64_round(ulong acc, ulong input)
|
||||
{
|
||||
acc += input * XXH_PRIME64_2;
|
||||
acc = XXH_rotl64(acc, 31);
|
||||
acc *= XXH_PRIME64_1;
|
||||
return acc;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH64_mergeRound(ulong acc, ulong val)
|
||||
{
|
||||
val = XXH64_round(0, val);
|
||||
acc ^= val;
|
||||
acc = acc * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||
return acc;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong XXH64_avalanche(ulong hash)
|
||||
{
|
||||
hash ^= hash >> 33;
|
||||
hash *= XXH_PRIME64_2;
|
||||
hash ^= hash >> 29;
|
||||
hash *= XXH_PRIME64_3;
|
||||
hash ^= hash >> 32;
|
||||
return hash;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong XXH64_finalize(ulong hash, byte* ptr, int len)
|
||||
{
|
||||
len &= 31;
|
||||
while (len >= 8) {
|
||||
ulong k1 = XXH64_round(0, *(ulong*)ptr);
|
||||
ptr += 8;
|
||||
hash ^= k1;
|
||||
hash = XXH_rotl64(hash,27) * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||
len -= 8;
|
||||
}
|
||||
if (len >= 4) {
|
||||
hash ^= *(uint*)ptr * XXH_PRIME64_1;
|
||||
ptr += 4;
|
||||
hash = XXH_rotl64(hash, 23) * XXH_PRIME64_2 + XXH_PRIME64_3;
|
||||
len -= 4;
|
||||
}
|
||||
while (len > 0) {
|
||||
hash ^= (*ptr++) * XXH_PRIME64_5;
|
||||
hash = XXH_rotl64(hash, 11) * XXH_PRIME64_1;
|
||||
--len;
|
||||
}
|
||||
return XXH64_avalanche(hash);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fd708be04cb928d4d8b419a27144213e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,266 @@
|
|||
// ReSharper disable InconsistentNaming
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Standart.Hash.xxHash
|
||||
{
|
||||
public static partial class xxHash64
|
||||
{
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte array
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe ulong ComputeHash(byte[] data, int length, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* pData = &data[0])
|
||||
{
|
||||
return UnsafeComputeHash(pData, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte array
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe ulong ComputeHash(byte[] data, int offset, int length, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(offset < data.Length);
|
||||
Debug.Assert(length <= data.Length - offset);
|
||||
|
||||
fixed (byte* pData = &data[0 + offset])
|
||||
{
|
||||
return UnsafeComputeHash(pData, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte array
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe ulong ComputeHash(System.ArraySegment<byte> data, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
|
||||
return ComputeHash(data.Array, data.Offset, data.Count, seed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the async stream
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream of data</param>
|
||||
/// <param name="bufferSize">The buffer size</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>The hash</returns>
|
||||
public static async ValueTask<ulong> ComputeHashAsync(Stream stream, int bufferSize = 8192, ulong seed = 0)
|
||||
{
|
||||
return await ComputeHashAsync(stream, bufferSize, seed, CancellationToken.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the async stream
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream of data</param>
|
||||
/// <param name="bufferSize">The buffer size</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <param name="cancellationToken">The cancelation token</param>
|
||||
/// <returns>The hash</returns>
|
||||
public static async ValueTask<ulong> ComputeHashAsync(Stream stream, int bufferSize, ulong seed,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
Debug.Assert(stream != null);
|
||||
Debug.Assert(bufferSize > 32);
|
||||
|
||||
// Optimizing memory allocation
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize + 32);
|
||||
|
||||
int readBytes;
|
||||
int offset = 0;
|
||||
long length = 0;
|
||||
|
||||
// Prepare the seed vector
|
||||
ulong v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2;
|
||||
ulong v2 = seed + XXH_PRIME64_2;
|
||||
ulong v3 = seed + 0;
|
||||
ulong v4 = seed - XXH_PRIME64_1;
|
||||
|
||||
try
|
||||
{
|
||||
// Read flow of bytes
|
||||
while ((readBytes =
|
||||
await stream.ReadAsync(buffer, offset, bufferSize, cancellationToken).ConfigureAwait(false)) > 0)
|
||||
{
|
||||
length = length + readBytes;
|
||||
offset = offset + readBytes;
|
||||
|
||||
if (offset < 32) continue;
|
||||
|
||||
int r = offset % 32; // remain
|
||||
int l = offset - r; // length
|
||||
|
||||
// Process the next chunk
|
||||
__inline__XXH64_stream_process(buffer, l, ref v1, ref v2, ref v3, ref v4);
|
||||
|
||||
// Put remaining bytes to buffer
|
||||
Utils.BlockCopy(buffer, l, buffer, 0, r);
|
||||
offset = r;
|
||||
}
|
||||
|
||||
// Process the final chunk
|
||||
ulong h64 = __inline__XXH64_stream_finalize(buffer, offset, ref v1, ref v2, ref v3, ref v4, length, seed);
|
||||
|
||||
return h64;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Free memory
|
||||
ArrayPool<byte>.Shared.Return(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte span
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe ulong ComputeHash(Span<byte> data, int length, ulong seed = 0)
|
||||
{
|
||||
//Debug.Assert(data != null);
|
||||
//Debug.Assert(length >= 0);
|
||||
//Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* pData = &MemoryMarshal.GetReference(data))
|
||||
{
|
||||
return UnsafeComputeHash(pData, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the data byte span
|
||||
/// </summary>
|
||||
/// <param name="data">The source of data</param>
|
||||
/// <param name="length">The length of the data for hashing</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe ulong ComputeHash(ReadOnlySpan<byte> data, int length, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(length >= 0);
|
||||
Debug.Assert(length <= data.Length);
|
||||
|
||||
fixed (byte* pData = &MemoryMarshal.GetReference(data))
|
||||
{
|
||||
return UnsafeComputeHash(pData, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the stream
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream of data</param>
|
||||
/// <param name="bufferSize">The buffer size</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>The hash</returns>
|
||||
public static ulong ComputeHash(Stream stream, int bufferSize = 8192, ulong seed = 0)
|
||||
{
|
||||
Debug.Assert(stream != null);
|
||||
Debug.Assert(bufferSize > 32);
|
||||
|
||||
// Optimizing memory allocation
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize + 32);
|
||||
|
||||
int readBytes;
|
||||
int offset = 0;
|
||||
long length = 0;
|
||||
|
||||
// Prepare the seed vector
|
||||
ulong v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2;
|
||||
ulong v2 = seed + XXH_PRIME64_2;
|
||||
ulong v3 = seed + 0;
|
||||
ulong v4 = seed - XXH_PRIME64_1;
|
||||
|
||||
try
|
||||
{
|
||||
// Read flow of bytes
|
||||
while ((readBytes = stream.Read(buffer, offset, bufferSize)) > 0)
|
||||
{
|
||||
length = length + readBytes;
|
||||
offset = offset + readBytes;
|
||||
|
||||
if (offset < 32) continue;
|
||||
|
||||
int r = offset % 32; // remain
|
||||
int l = offset - r; // length
|
||||
|
||||
// Process the next chunk
|
||||
__inline__XXH64_stream_process(buffer, l, ref v1, ref v2, ref v3, ref v4);
|
||||
|
||||
// Put remaining bytes to buffer
|
||||
Utils.BlockCopy(buffer, l, buffer, 0, r);
|
||||
offset = r;
|
||||
}
|
||||
|
||||
// Process the final chunk
|
||||
ulong h64 = __inline__XXH64_stream_finalize(buffer, offset, ref v1, ref v2, ref v3, ref v4, length, seed);
|
||||
|
||||
return h64;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Free memory
|
||||
ArrayPool<byte>.Shared.Return(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute xxHash for the string
|
||||
/// </summary>
|
||||
/// <param name="str">The source of data</param>
|
||||
/// <param name="seed">The seed number</param>
|
||||
/// <returns>hash</returns>
|
||||
public static unsafe ulong ComputeHash(string str, uint seed = 0)
|
||||
{
|
||||
Debug.Assert(str != null);
|
||||
|
||||
fixed (char* c = str)
|
||||
{
|
||||
byte* ptr = (byte*) c;
|
||||
int length = str.Length * 2;
|
||||
|
||||
return UnsafeComputeHash(ptr, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe ulong UnsafeComputeHash(byte* ptr, int length, ulong seed)
|
||||
{
|
||||
// Use inlined version
|
||||
// return XXH64(ptr, length, seed);
|
||||
|
||||
return __inline__XXH64(ptr, length, seed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2ca6cc6a152389145bc1ef4f745d636e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Reference in New Issue