海淀天下城电子沙盘单机版
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

924 lines
35 KiB

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Reflection.Emit;
using System.Reflection;
namespace MessagePack.Internal
{
// Key = long, Value = int for UTF8String Dictionary
public class AutomataDictionary : IEnumerable<KeyValuePair<string, int>>
{
readonly AutomataNode root;
public AutomataDictionary()
{
root = new AutomataNode(0);
}
#if NETSTANDARD
public unsafe void Add(string str, int value)
{
var bytes = Encoding.UTF8.GetBytes(str);
fixed (byte* buffer = &bytes[0])
{
var node = root;
var p = buffer;
var rest = bytes.Length;
while (rest != 0)
{
var key = AutomataKeyGen.GetKey(ref p, ref rest);
if (rest == 0)
{
node = node.Add(key, value, str);
}
else
{
node = node.Add(key);
}
}
}
}
public unsafe bool TryGetValue(byte[] bytes, int offset, int count, out int value)
{
fixed (byte* p = &bytes[0])
{
var p1 = p;
var node = root;
var rest = count;
while (rest != 0 && node != null)
{
node = node.SearchNext(ref p1, ref rest);
}
if (node == null)
{
value = -1;
return false;
}
else
{
value = node.Value;
return true;
}
}
}
#else
// for Unity, use safe only.
public void Add(string str, int value)
{
var bytes = Encoding.UTF8.GetBytes(str);
var offset = 0;
var node = root;
var rest = bytes.Length;
while (rest != 0)
{
var key = AutomataKeyGen.GetKeySafe(bytes, ref offset, ref rest);
if (rest == 0)
{
node = node.Add(key, value, str);
}
else
{
node = node.Add(key);
}
}
}
#endif
public bool TryGetValueSafe(ArraySegment<byte> key, out int value)
{
var node = root;
var bytes = key.Array;
var offset = key.Offset;
var rest = key.Count;
while (rest != 0 && node != null)
{
node = node.SearchNextSafe(bytes, ref offset, ref rest);
}
if (node == null)
{
value = -1;
return false;
}
else
{
value = node.Value;
return true;
}
}
// for debugging
public override string ToString()
{
var sb = new StringBuilder();
ToStringCore(root.YieldChildren(), sb, 0);
return sb.ToString();
}
static void ToStringCore(IEnumerable<AutomataNode> nexts, StringBuilder sb, int depth)
{
foreach (var item in nexts)
{
if (depth != 0)
{
sb.Append(' ', depth * 2);
}
sb.Append("[" + item.Key + "]");
if (item.Value != -1)
{
sb.Append("(" + item.originalKey + ")");
sb.Append(" = ");
sb.Append(item.Value);
}
sb.AppendLine();
ToStringCore(item.YieldChildren(), sb, depth + 1);
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerator<KeyValuePair<string, int>> GetEnumerator()
{
return YieldCore(this.root.YieldChildren()).GetEnumerator();
}
static IEnumerable<KeyValuePair<string, int>> YieldCore(IEnumerable<AutomataNode> nexts)
{
foreach (var item in nexts)
{
if (item.Value != -1) yield return new KeyValuePair<string, int>(item.originalKey, item.Value);
foreach (var x in YieldCore(item.YieldChildren())) yield return x;
}
}
// IL Emit
#if !NET_STANDARD_2_0
public void EmitMatch(ILGenerator il, LocalBuilder p, LocalBuilder rest, LocalBuilder key, Action<KeyValuePair<string, int>> onFound, Action onNotFound)
{
root.EmitSearchNext(il, p, rest, key, onFound, onNotFound);
}
#endif
class AutomataNode : IComparable<AutomataNode>
{
static readonly AutomataNode[] emptyNodes = new AutomataNode[0];
static readonly ulong[] emptyKeys = new ulong[0];
public ulong Key;
public int Value;
public string originalKey;
AutomataNode[] nexts;
ulong[] nextKeys;
int count;
public bool HasChildren { get { return count != 0; } }
public AutomataNode(ulong key)
{
this.Key = key;
this.Value = -1;
this.nexts = emptyNodes;
this.nextKeys = emptyKeys;
this.count = 0;
this.originalKey = null;
}
public AutomataNode Add(ulong key)
{
var index = Array.BinarySearch(nextKeys, 0, count, key);
if (index < 0)
{
if (nexts.Length == count)
{
Array.Resize<AutomataNode>(ref nexts, (count == 0) ? 4 : (count * 2));
Array.Resize<ulong>(ref nextKeys, (count == 0) ? 4 : (count * 2));
}
count++;
var nextNode = new AutomataNode(key);
nexts[count - 1] = nextNode;
nextKeys[count - 1] = key;
Array.Sort(nexts, 0, count);
Array.Sort(nextKeys, 0, count);
return nextNode;
}
else
{
return nexts[index];
}
}
public AutomataNode Add(ulong key, int value, string originalKey)
{
var v = Add(key);
v.Value = value;
v.originalKey = originalKey;
return v;
}
#if NETSTANDARD
public unsafe AutomataNode SearchNext(ref byte* p, ref int rest)
{
var key = AutomataKeyGen.GetKey(ref p, ref rest);
if (count < 4)
{
// linear search
for (int i = 0; i < count; i++)
{
if (nextKeys[i] == key)
{
return nexts[i];
}
}
}
else
{
// binary search
var index = BinarySearch(nextKeys, 0, count, key);
if (index >= 0)
{
return nexts[index];
}
}
return null;
}
#endif
public AutomataNode SearchNextSafe(byte[] p, ref int offset, ref int rest)
{
var key = AutomataKeyGen.GetKeySafe(p, ref offset, ref rest);
if (count < 4)
{
// linear search
for (int i = 0; i < count; i++)
{
if (nextKeys[i] == key)
{
return nexts[i];
}
}
}
else
{
// binary search
var index = BinarySearch(nextKeys, 0, count, key);
if (index >= 0)
{
return nexts[index];
}
}
return null;
}
internal static int BinarySearch(ulong[] array, int index, int length, ulong value)
{
int lo = index;
int hi = index + length - 1;
while (lo <= hi)
{
int i = lo + ((hi - lo) >> 1);
var arrayValue = array[i];
int order;
if (arrayValue < value) order = -1;
else if (arrayValue > value) order = 1;
else order = 0;
if (order == 0) return i;
if (order < 0)
{
lo = i + 1;
}
else
{
hi = i - 1;
}
}
return ~lo;
}
public int CompareTo(AutomataNode other)
{
return this.Key.CompareTo(other.Key);
}
public IEnumerable<AutomataNode> YieldChildren()
{
for (int i = 0; i < count; i++)
{
yield return nexts[i];
}
}
#if !NET_STANDARD_2_0
// SearchNext(ref byte* p, ref int rest, ref ulong key)
public void EmitSearchNext(ILGenerator il, LocalBuilder p, LocalBuilder rest, LocalBuilder key, Action<KeyValuePair<string, int>> onFound, Action onNotFound)
{
// key = AutomataKeyGen.GetKey(ref p, ref rest);
il.EmitLdloca(p);
il.EmitLdloca(rest);
#if NETSTANDARD
il.EmitCall(AutomataKeyGen.GetKeyMethod);
#else
il.EmitCall(AutomataKeyGen.GetGetKeyMethod());
#endif
il.EmitStloc(key);
// match children.
EmitSearchNextCore(il, p, rest, key, onFound, onNotFound, nexts, count);
}
static void EmitSearchNextCore(ILGenerator il, LocalBuilder p, LocalBuilder rest, LocalBuilder key, Action<KeyValuePair<string, int>> onFound, Action onNotFound, AutomataNode[] nexts, int count)
{
if (count < 4)
{
// linear-search
var valueExists = nexts.Take(count).Where(x => x.Value != -1).ToArray();
var childrenExists = nexts.Take(count).Where(x => x.HasChildren).ToArray();
var gotoSearchNext = il.DefineLabel();
var gotoNotFound = il.DefineLabel();
{
il.EmitLdloc(rest);
if (childrenExists.Length != 0 && valueExists.Length == 0)
{
il.Emit(OpCodes.Brfalse, gotoNotFound); // if(rest == 0)
}
else
{
il.Emit(OpCodes.Brtrue, gotoSearchNext); // if(rest != 0)
}
}
{
var ifValueNexts = Enumerable.Range(0, Math.Max(valueExists.Length - 1, 0)).Select(_ => il.DefineLabel()).ToArray();
for (int i = 0; i < valueExists.Length; i++)
{
var notFoundLabel = il.DefineLabel();
if (i != 0)
{
il.MarkLabel(ifValueNexts[i - 1]);
}
il.EmitLdloc(key);
il.EmitULong(valueExists[i].Key);
il.Emit(OpCodes.Bne_Un, notFoundLabel);
// found
onFound(new KeyValuePair<string, int>(valueExists[i].originalKey, valueExists[i].Value));
// notfound
il.MarkLabel(notFoundLabel);
if (i != valueExists.Length - 1)
{
il.Emit(OpCodes.Br, ifValueNexts[i]);
}
else
{
onNotFound();
}
}
}
il.MarkLabel(gotoSearchNext);
var ifRecNext = Enumerable.Range(0, Math.Max(childrenExists.Length - 1, 0)).Select(_ => il.DefineLabel()).ToArray();
for (int i = 0; i < childrenExists.Length; i++)
{
var notFoundLabel = il.DefineLabel();
if (i != 0)
{
il.MarkLabel(ifRecNext[i - 1]);
}
il.EmitLdloc(key);
il.EmitULong(childrenExists[i].Key);
il.Emit(OpCodes.Bne_Un, notFoundLabel);
// found
childrenExists[i].EmitSearchNext(il, p, rest, key, onFound, onNotFound);
// notfound
il.MarkLabel(notFoundLabel);
if (i != childrenExists.Length - 1)
{
il.Emit(OpCodes.Br, ifRecNext[i]);
}
else
{
onNotFound();
}
}
il.MarkLabel(gotoNotFound);
onNotFound();
}
else
{
// binary-search
var midline = count / 2;
var mid = nexts[midline].Key;
var l = nexts.Take(count).Take(midline).ToArray();
var r = nexts.Take(count).Skip(midline).ToArray();
var gotoRight = il.DefineLabel();
// if(key < mid)
il.EmitLdloc(key);
il.EmitULong(mid);
il.Emit(OpCodes.Bge, gotoRight);
EmitSearchNextCore(il, p, rest, key, onFound, onNotFound, l, l.Length);
// else
il.MarkLabel(gotoRight);
EmitSearchNextCore(il, p, rest, key, onFound, onNotFound, r, r.Length);
}
}
#endif
}
}
public static class AutomataKeyGen
{
public delegate ulong PointerDelegate<T>(ref T p, ref int rest);
#if NETSTANDARD
public static readonly MethodInfo GetKeyMethod = typeof(AutomataKeyGen).GetRuntimeMethod("GetKey", new[] { typeof(byte).MakePointerType().MakeByRefType(), typeof(int).MakeByRefType() });
#endif
#if !NETSTANDARD
#if !NET_STANDARD_2_0
static MethodInfo dynamicGetKeyMethod;
static readonly object gate = new object();
static DynamicAssembly dynamicAssembly;
public static MethodInfo GetGetKeyMethod()
{
if (dynamicGetKeyMethod == null)
{
lock (gate)
{
if (dynamicGetKeyMethod == null)
{
dynamicAssembly = new DynamicAssembly("AutomataKeyGenHelper");
var helperType = dynamicAssembly.DefineType("AutomataKeyGen", TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Abstract, null);
var dm = helperType.DefineMethod("GetKey", MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, typeof(ulong), new[] { typeof(byte).MakePointerType().MakeByRefType(), typeof(int).MakeByRefType() });
var il = dm.GetILGenerator();
il.DeclareLocal(typeof(int)); // var readSize
il.DeclareLocal(typeof(ulong)); // var key =
il.DeclareLocal(typeof(int)); // var _local =
var elseLabel = il.DefineLabel();
var endLabel = il.DefineLabel();
var case0 = il.DefineLabel();
var case1 = il.DefineLabel();
var case2 = il.DefineLabel();
var case3 = il.DefineLabel();
var case4 = il.DefineLabel();
var case5 = il.DefineLabel();
var case6 = il.DefineLabel();
var case7 = il.DefineLabel();
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldind_I4);
il.Emit(OpCodes.Ldc_I4_8);
il.Emit(OpCodes.Blt_S, elseLabel);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldind_I);
il.Emit(OpCodes.Ldind_I8);
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldc_I4_8);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Br, endLabel);
il.MarkLabel(elseLabel);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldind_I4);
il.Emit(OpCodes.Stloc_2);
il.Emit(OpCodes.Ldloc_2);
il.Emit(OpCodes.Switch, new[] { case0, case1, case2, case3, case4, case5, case6, case7 });
il.Emit(OpCodes.Br, case0); // default
il.MarkLabel(case1);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldind_I);
il.Emit(OpCodes.Ldind_U1);
il.Emit(OpCodes.Conv_U8);
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Br, endLabel);
il.MarkLabel(case2);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldind_I);
il.Emit(OpCodes.Ldind_U2);
il.Emit(OpCodes.Conv_U8);
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldc_I4_2);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Br, endLabel);
il.MarkLabel(case3);
il.DeclareLocal(typeof(ushort)); // _3
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldind_I);
il.Emit(OpCodes.Ldind_U1);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldind_I);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Ldind_U2);
il.Emit(OpCodes.Stloc_3);
il.Emit(OpCodes.Conv_U8);
il.Emit(OpCodes.Ldloc_3);
il.Emit(OpCodes.Conv_U8);
il.Emit(OpCodes.Ldc_I4_8);
il.Emit(OpCodes.Shl);
il.Emit(OpCodes.Or);
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldc_I4_3);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Br, endLabel);
il.MarkLabel(case4);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldind_I);
il.Emit(OpCodes.Ldind_U4);
il.Emit(OpCodes.Conv_U8);
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldc_I4_4);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Br, endLabel);
il.MarkLabel(case5);
il.DeclareLocal(typeof(uint)); // _4
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldind_I);
il.Emit(OpCodes.Ldind_U1);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldind_I);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Ldind_U4);
il.Emit(OpCodes.Stloc_S, 4);
il.Emit(OpCodes.Conv_U8);
il.Emit(OpCodes.Ldloc_S, 4);
il.Emit(OpCodes.Conv_U8);
il.Emit(OpCodes.Ldc_I4_8);
il.Emit(OpCodes.Shl);
il.Emit(OpCodes.Or);
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldc_I4_5);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Br, endLabel);
il.MarkLabel(case6);
il.DeclareLocal(typeof(ulong)); // _5
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldind_I);
il.Emit(OpCodes.Ldind_U2);
il.Emit(OpCodes.Conv_U8); // [x]
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldind_I);
il.Emit(OpCodes.Ldc_I4_2);
il.Emit(OpCodes.Add); // [x, y]
il.Emit(OpCodes.Ldind_U4);
il.Emit(OpCodes.Conv_U8);
il.Emit(OpCodes.Stloc_S, 5); // [x]
il.Emit(OpCodes.Ldloc_S, 5);
il.Emit(OpCodes.Ldc_I4_S, 16);
il.Emit(OpCodes.Shl);
il.Emit(OpCodes.Or);
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldc_I4_6);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Br, endLabel);
il.MarkLabel(case7);
il.DeclareLocal(typeof(ushort)); // _6
il.DeclareLocal(typeof(uint)); // _7
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldind_I);
il.Emit(OpCodes.Ldind_U1);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldind_I);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Ldind_U2);
il.Emit(OpCodes.Stloc_S, 6);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldind_I);
il.Emit(OpCodes.Ldc_I4_3);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Ldind_U4);
il.Emit(OpCodes.Stloc_S, 7);
il.Emit(OpCodes.Conv_U8);
il.Emit(OpCodes.Ldloc_S, 6);
il.Emit(OpCodes.Conv_U8);
il.Emit(OpCodes.Ldc_I4_8);
il.Emit(OpCodes.Shl);
il.Emit(OpCodes.Or);
il.Emit(OpCodes.Ldloc_S, 7);
il.Emit(OpCodes.Conv_U8);
il.Emit(OpCodes.Ldc_I4_S, 24);
il.Emit(OpCodes.Shl);
il.Emit(OpCodes.Or);
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldc_I4_7);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Br, endLabel);
il.MarkLabel(case0);
il.Emit(OpCodes.Ldstr, "Not Supported Length");
il.Emit(OpCodes.Newobj, typeof(InvalidOperationException).GetConstructor(new[] { typeof(string) }));
il.Emit(OpCodes.Throw);
il.MarkLabel(endLabel);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldind_I);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Stind_I);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldind_I4);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Sub);
il.Emit(OpCodes.Stind_I4);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ret);
var genereatedType = helperType.CreateTypeInfo().AsType();
dynamicGetKeyMethod = genereatedType.GetMethods().First();
}
}
}
return dynamicGetKeyMethod;
}
#endif
#endif
#if NETSTANDARD
public static unsafe ulong GetKey(ref byte* p, ref int rest)
{
int readSize;
ulong key;
unchecked
{
if (rest >= 8)
{
key = *(ulong*)p;
readSize = 8;
}
else
{
switch (rest)
{
case 1:
{
key = *(byte*)p;
readSize = 1;
break;
}
case 2:
{
key = *(ushort*)p;
readSize = 2;
break;
}
case 3:
{
var a = *p;
var b = *(ushort*)(p + 1);
key = ((ulong)a | (ulong)b << 8);
readSize = 3;
break;
}
case 4:
{
key = *(uint*)p;
readSize = 4;
break;
}
case 5:
{
var a = *p;
var b = *(uint*)(p + 1);
key = ((ulong)a | (ulong)b << 8);
readSize = 5;
break;
}
case 6:
{
ulong a = *(ushort*)p;
ulong b = *(uint*)(p + 2);
key = (a | (b << 16));
readSize = 6;
break;
}
case 7:
{
var a = *(byte*)p;
var b = *(ushort*)(p + 1);
var c = *(uint*)(p + 3);
key = ((ulong)a | (ulong)b << 8 | (ulong)c << 24);
readSize = 7;
break;
}
default:
throw new InvalidOperationException("Not Supported Length");
}
}
p += readSize;
rest -= readSize;
return key;
}
}
#endif
public static ulong GetKeySafe(byte[] bytes, ref int offset, ref int rest)
{
int readSize;
ulong key;
if (BitConverter.IsLittleEndian)
{
unchecked
{
if (rest >= 8)
{
key = (ulong)bytes[offset] << 0 | (ulong)bytes[offset + 1] << 8 | (ulong)bytes[offset + 2] << 16 | (ulong)bytes[offset + 3] << 24
| (ulong)bytes[offset + 4] << 32 | (ulong)bytes[offset + 5] << 40 | (ulong)bytes[offset + 6] << 48 | (ulong)bytes[offset + 7] << 56;
readSize = 8;
}
else
{
switch (rest)
{
case 1:
{
key = bytes[offset];
readSize = 1;
break;
}
case 2:
{
key = (ulong)bytes[offset] << 0 | (ulong)bytes[offset + 1] << 8;
readSize = 2;
break;
}
case 3:
{
key = (ulong)bytes[offset] << 0 | (ulong)bytes[offset + 1] << 8 | (ulong)bytes[offset + 2] << 16;
readSize = 3;
break;
}
case 4:
{
key = (ulong)bytes[offset] << 0 | (ulong)bytes[offset + 1] << 8 | (ulong)bytes[offset + 2] << 16 | (ulong)bytes[offset + 3] << 24;
readSize = 4;
break;
}
case 5:
{
key = (ulong)bytes[offset] << 0 | (ulong)bytes[offset + 1] << 8 | (ulong)bytes[offset + 2] << 16 | (ulong)bytes[offset + 3] << 24
| (ulong)bytes[offset + 4] << 32;
readSize = 5;
break;
}
case 6:
{
key = (ulong)bytes[offset] << 0 | (ulong)bytes[offset + 1] << 8 | (ulong)bytes[offset + 2] << 16 | (ulong)bytes[offset + 3] << 24
| (ulong)bytes[offset + 4] << 32 | (ulong)bytes[offset + 5] << 40;
readSize = 6;
break;
}
case 7:
{
key = (ulong)bytes[offset] << 0 | (ulong)bytes[offset + 1] << 8 | (ulong)bytes[offset + 2] << 16 | (ulong)bytes[offset + 3] << 24
| (ulong)bytes[offset + 4] << 32 | (ulong)bytes[offset + 5] << 40 | (ulong)bytes[offset + 6] << 48;
readSize = 7;
break;
}
default:
throw new InvalidOperationException("Not Supported Length");
}
}
offset += readSize;
rest -= readSize;
return key;
}
}
else
{
unchecked
{
if (rest >= 8)
{
key = (ulong)bytes[offset] << 56 | (ulong)bytes[offset + 1] << 48 | (ulong)bytes[offset + 2] << 40 | (ulong)bytes[offset + 3] << 32
| (ulong)bytes[offset + 4] << 24 | (ulong)bytes[offset + 5] << 16 | (ulong)bytes[offset + 6] << 8 | (ulong)bytes[offset + 7];
readSize = 8;
}
else
{
switch (rest)
{
case 1:
{
key = bytes[offset];
readSize = 1;
break;
}
case 2:
{
key = (ulong)bytes[offset] << 8 | (ulong)bytes[offset + 1] << 0;
readSize = 2;
break;
}
case 3:
{
key = (ulong)bytes[offset] << 16 | (ulong)bytes[offset + 1] << 8 | (ulong)bytes[offset + 2] << 0;
readSize = 3;
break;
}
case 4:
{
key = (ulong)bytes[offset] << 24 | (ulong)bytes[offset + 1] << 16 | (ulong)bytes[offset + 2] << 8 | (ulong)bytes[offset + 3] << 0;
readSize = 4;
break;
}
case 5:
{
key = (ulong)bytes[offset] << 32 | (ulong)bytes[offset + 1] << 24 | (ulong)bytes[offset + 2] << 16 | (ulong)bytes[offset + 3] << 8
| (ulong)bytes[offset + 4] << 0;
readSize = 5;
break;
}
case 6:
{
key = (ulong)bytes[offset] << 40 | (ulong)bytes[offset + 1] << 32 | (ulong)bytes[offset + 2] << 24 | (ulong)bytes[offset + 3] << 16
| (ulong)bytes[offset + 4] << 8 | (ulong)bytes[offset + 5] << 0;
readSize = 6;
break;
}
case 7:
{
key = (ulong)bytes[offset] << 48 | (ulong)bytes[offset + 1] << 40 | (ulong)bytes[offset + 2] << 32 | (ulong)bytes[offset + 3] << 24
| (ulong)bytes[offset + 4] << 16 | (ulong)bytes[offset + 5] << 8 | (ulong)bytes[offset + 6] << 0;
readSize = 7;
break;
}
default:
throw new InvalidOperationException("Not Supported Length");
}
}
offset += readSize;
rest -= readSize;
return key;
}
}
}
}
}