diff --git a/Assets/Scenes/Version2.unity b/Assets/Scenes/Version2.unity
index 119b79b..269dacf 100644
--- a/Assets/Scenes/Version2.unity
+++ b/Assets/Scenes/Version2.unity
@@ -30122,6 +30122,7 @@ GameObject:
- component: {fileID: 1564959565}
- component: {fileID: 1564959567}
- component: {fileID: 1564959568}
+ - component: {fileID: 1564959569}
m_Layer: 0
m_Name: ViewerMain
m_TagString: Untagged
@@ -30275,6 +30276,18 @@ MonoBehaviour:
type: 2}
AnimationCameraAnimator: {fileID: 1468470379}
AnimationCamera: {fileID: 790387849}
+--- !u!114 &1564959569
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1564959564}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 822adc4dd85200142901586dd5c697c6, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
--- !u!1 &1566898429
GameObject:
m_ObjectHideFlags: 0
diff --git a/Assets/Scripts/BaseNcoding.meta b/Assets/Scripts/BaseNcoding.meta
new file mode 100644
index 0000000..1cf72b5
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 8efe8ce6fc7c3d84db812df72e79c7ce
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/BaseNcoding/Base.cs b/Assets/Scripts/BaseNcoding/Base.cs
new file mode 100644
index 0000000..8dd9dfc
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding/Base.cs
@@ -0,0 +1,184 @@
+using System;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace BaseNcoding
+{
+ public abstract class Base
+ {
+ public uint CharsCount { get; }
+
+ public double BitsPerChars => (double)BlockBitsCount / BlockCharsCount;
+
+ public int BlockBitsCount { get; protected set; }
+
+ public int BlockCharsCount { get; protected set; }
+
+ public string Alphabet { get; }
+
+ public char Special { get; }
+
+ public abstract bool HasSpecial { get; }
+
+ public Encoding Encoding { get; set; }
+
+ public bool Parallel { get; set; }
+
+ protected readonly int[] InvAlphabet;
+
+ public Base(uint charsCount, string alphabet, char special, Encoding encoding = null, bool parallel = false)
+ {
+ if (alphabet.Length != charsCount)
+ throw new ArgumentException($"Base string should contain {charsCount} chars");
+
+ for (int i = 0; i < charsCount; i++)
+ for (int j = i + 1; j < charsCount; j++)
+ if (alphabet[i] == alphabet[j])
+ throw new ArgumentException("Base string should contain distinct chars");
+
+ if (alphabet.Contains(special))
+ throw new ArgumentException("Base string should not contain special char");
+
+ CharsCount = charsCount;
+ Alphabet = alphabet;
+ Special = special;
+ int bitsPerChar = LogBase2(charsCount);
+ BlockBitsCount = Lcm(bitsPerChar, 8);
+ BlockCharsCount = BlockBitsCount / bitsPerChar;
+
+ InvAlphabet = new int[Alphabet.Max() + 1];
+
+ for (int i = 0; i < InvAlphabet.Length; i++)
+ InvAlphabet[i] = -1;
+
+ for (int i = 0; i < charsCount; i++)
+ InvAlphabet[Alphabet[i]] = i;
+
+ Encoding = encoding ?? Encoding.UTF8;
+ Parallel = parallel;
+ }
+
+ public virtual string EncodeString(string data)
+ {
+ return Encode(Encoding.GetBytes(data));
+ }
+
+ public abstract string Encode(byte[] data);
+
+ public string DecodeToString(string data)
+ {
+ return Encoding.GetString(Decode(Regex.Replace(data, @"\r\n?|\n", "")));
+ }
+
+ public abstract byte[] Decode(string data);
+
+ ///
+ /// From: http://stackoverflow.com/a/600306/1046374
+ ///
+ ///
+ ///
+ public static bool IsPowerOf2(uint x)
+ {
+ uint xint = x;
+ if (x - xint != 0)
+ return false;
+
+ return (xint & (xint - 1)) == 0;
+ }
+
+ ///
+ /// From: http://stackoverflow.com/a/13569863/1046374
+ ///
+ public static int Lcm(int a, int b)
+ {
+ int num1, num2;
+ if (a > b)
+ {
+ num1 = a;
+ num2 = b;
+ }
+ else
+ {
+ num1 = b;
+ num2 = a;
+ }
+
+ for (int i = 1; i <= num2; i++)
+ {
+ int mult = num1 * i;
+ if (mult % num2 == 0)
+ return mult;
+ }
+
+ return num2;
+ }
+
+ private static int LogBase2(uint x)
+ {
+ int r = 0;
+ while ((x >>= 1) != 0)
+ r++;
+ return r;
+ }
+
+ private static int LogBaseN(uint x, uint n)
+ {
+ int r = 0;
+ while ((x /= n) != 0)
+ r++;
+ return r;
+ }
+
+ public static int GetOptimalBitsCount2(uint charsCount, out uint charsCountInBits,
+ uint maxBitsCount = 64, bool base2BitsCount = false)
+ {
+ int result = 0;
+ charsCountInBits = 0;
+ int n1 = LogBase2(charsCount);
+ double charsCountLog = Math.Log(2, charsCount);
+ double maxRatio = 0;
+
+ for (int n = n1; n <= maxBitsCount; n++)
+ {
+ if (base2BitsCount && n % 8 != 0)
+ continue;
+
+ uint l1 = (uint)Math.Ceiling(n * charsCountLog);
+ double ratio = (double)n / l1;
+ if (ratio > maxRatio)
+ {
+ maxRatio = ratio;
+ result = n;
+ charsCountInBits = l1;
+ }
+ }
+
+ return result;
+ }
+
+ protected static int GetOptimalBitsCount(uint charsCount, out uint charsCountInBits,
+ uint maxBitsCount = 64, uint radix = 2)
+ {
+ int result = 0;
+ charsCountInBits = 0;
+ int n0 = LogBaseN(charsCount, radix);
+ double charsCountLog = Math.Log(radix, charsCount);
+ double maxRatio = 0;
+
+ for (int n = n0; n <= maxBitsCount; n++)
+ {
+ uint k = (uint)Math.Ceiling(n * charsCountLog);
+ double ratio = (double)n / k;
+ if (ratio > maxRatio)
+ {
+ maxRatio = ratio;
+ result = n;
+ charsCountInBits = k;
+ }
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/Assets/Scripts/BaseNcoding/Base.cs.meta b/Assets/Scripts/BaseNcoding/Base.cs.meta
new file mode 100644
index 0000000..904a5d4
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding/Base.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: dddac6b0e9d7d75489cf3110fcc3a611
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/BaseNcoding/Base256.cs b/Assets/Scripts/BaseNcoding/Base256.cs
new file mode 100644
index 0000000..8a90ef2
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding/Base256.cs
@@ -0,0 +1,41 @@
+using System.Text;
+
+namespace BaseNcoding
+{
+ public class Base256 : Base
+ {
+ public const string DefaultAlphabet = "!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁł";
+ public const char DefaultSpecial = (char)0;
+
+ public override bool HasSpecial => false;
+
+ public Base256(string alphabet = DefaultAlphabet, char special = DefaultSpecial,
+ Encoding textEncoding = null)
+ : base(256, alphabet, special, textEncoding)
+ {
+ }
+
+ public override string Encode(byte[] data)
+ {
+ var result = new char[data.Length];
+
+ for (int i = 0; i < data.Length; i++)
+ result[i] = Alphabet[data[i]];
+
+ return new string(result);
+ }
+
+ public override byte[] Decode(string data)
+ {
+ unchecked
+ {
+ byte[] result = new byte[data.Length];
+
+ for (int i = 0; i < data.Length; i++)
+ result[i] = (byte)InvAlphabet[data[i]];
+
+ return result;
+ }
+ }
+ }
+}
diff --git a/Assets/Scripts/BaseNcoding/Base256.cs.meta b/Assets/Scripts/BaseNcoding/Base256.cs.meta
new file mode 100644
index 0000000..5d61cf6
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding/Base256.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b84ecd8bc32acb7448d64c9bb045948d
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/BaseNcoding/Base32.cs b/Assets/Scripts/BaseNcoding/Base32.cs
new file mode 100644
index 0000000..33b70ff
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding/Base32.cs
@@ -0,0 +1,203 @@
+using System.Text;
+
+namespace BaseNcoding
+{
+ public class Base32 : Base
+ {
+ public const string DefaultAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
+ public const char DefaultSpecial = '>';
+
+ public override bool HasSpecial => true;
+
+ public Base32(string alphabet = DefaultAlphabet, char special = DefaultSpecial, Encoding textEncoding = null)
+ : base(32, alphabet, special, textEncoding)
+ {
+ }
+
+ public override string Encode(byte[] data)
+ {
+ int dataLength = data.Length;
+ StringBuilder result = new StringBuilder((dataLength + 4) / 5 * 8);
+
+ byte x1, x2;
+ int i;
+
+ int length5 = (dataLength / 5) * 5;
+ for (i = 0; i < length5; i += 5)
+ {
+ x1 = data[i];
+ result.Append(Alphabet[x1 >> 3]);
+
+ x2 = data[i + 1];
+ result.Append(Alphabet[((x1 << 2) & 0x1C) | (x2 >> 6)]);
+ result.Append(Alphabet[(x2 >> 1) & 0x1F]);
+
+ x1 = data[i + 2];
+ result.Append(Alphabet[((x2 << 4) & 0x10) | (x1 >> 4)]);
+
+ x2 = data[i + 3];
+ result.Append(Alphabet[((x1 << 1) & 0x1E) | (x2 >> 7)]);
+ result.Append(Alphabet[(x2 >> 2) & 0x1F]);
+
+ x1 = data[i + 4];
+ result.Append(Alphabet[((x2 << 3) & 0x18) | (x1 >> 5)]);
+ result.Append(Alphabet[x1 & 0x1F]);
+ }
+
+ switch (dataLength - length5)
+ {
+ case 1:
+ x1 = data[i];
+ result.Append(Alphabet[x1 >> 3]);
+ result.Append(Alphabet[(x1 << 2) & 0x1C]);
+
+ result.Append(Special, 6);
+ break;
+ case 2:
+ x1 = data[i];
+ result.Append(Alphabet[x1 >> 3]);
+ x2 = data[i + 1];
+ result.Append(Alphabet[((x1 << 2) & 0x1C) | (x2 >> 6)]);
+ result.Append(Alphabet[(x2 >> 1) & 0x1F]);
+ result.Append(Alphabet[(x2 << 4) & 0x10]);
+
+ result.Append(Special, 4);
+ break;
+ case 3:
+ x1 = data[i];
+ result.Append(Alphabet[x1 >> 3]);
+ x2 = data[i + 1];
+ result.Append(Alphabet[((x1 << 2) & 0x1C) | (x2 >> 6)]);
+ result.Append(Alphabet[(x2 >> 1) & 0x1F]);
+ x1 = data[i + 2];
+ result.Append(Alphabet[((x2 << 4) & 0x10) | (x1 >> 4)]);
+ result.Append(Alphabet[(x1 << 1) & 0x1E]);
+
+ result.Append(Special, 3);
+ break;
+ case 4:
+ x1 = data[i];
+ result.Append(Alphabet[x1 >> 3]);
+ x2 = data[i + 1];
+ result.Append(Alphabet[((x1 << 2) & 0x1C) | (x2 >> 6)]);
+ result.Append(Alphabet[(x2 >> 1) & 0x1F]);
+ x1 = data[i + 2];
+ result.Append(Alphabet[((x2 << 4) & 0x10) | (x1 >> 4)]);
+ x2 = data[i + 3];
+ result.Append(Alphabet[((x1 << 1) & 0x1E) | (x2 >> 7)]);
+ result.Append(Alphabet[(x2 >> 2) & 0x1F]);
+ result.Append(Alphabet[(x2 << 3) & 0x18]);
+
+ result.Append(Special);
+ break;
+ }
+
+ return result.ToString();
+ }
+
+ public override byte[] Decode(string data)
+ {
+ unchecked
+ {
+ if (string.IsNullOrEmpty(data))
+ return new byte[0];
+
+ int additionalBytes = 0, diff = 0, tempLen = 0;
+
+
+ int lastSpecialInd = data.Length;
+ while (data[lastSpecialInd - 1] == Special)
+ lastSpecialInd--;
+ int tailLength = data.Length - lastSpecialInd;
+
+ switch (tailLength)
+ {
+ case 6:
+ additionalBytes = 4;
+ break;
+ case 4:
+ additionalBytes = 3;
+ break;
+ case 3:
+ additionalBytes = 2;
+ break;
+ case 1:
+ additionalBytes = 1;
+ break;
+ }
+
+ diff = tailLength - additionalBytes;
+ tailLength = additionalBytes;
+ tempLen = data.Length - diff;
+
+ byte[] result = new byte[(tempLen + 7) / 8 * 5 - tailLength];
+ int length5 = result.Length / 5 * 5;
+ int x1, x2, x3, x4, x5, x6, x7, x8;
+
+ int i, srcInd = 0;
+ for (i = 0; i < length5; i += 5)
+ {
+ x1 = InvAlphabet[data[srcInd++]];
+ x2 = InvAlphabet[data[srcInd++]];
+ x3 = InvAlphabet[data[srcInd++]];
+ x4 = InvAlphabet[data[srcInd++]];
+ x5 = InvAlphabet[data[srcInd++]];
+ x6 = InvAlphabet[data[srcInd++]];
+ x7 = InvAlphabet[data[srcInd++]];
+ x8 = InvAlphabet[data[srcInd++]];
+
+ result[i] = (byte)((x1 << 3) | ((x2 >> 2) & 0x07));
+ result[i + 1] = (byte)((x2 << 6) | ((x3 << 1) & 0x3E) | ((x4 >> 4) & 0x01));
+ result[i + 2] = (byte)((x4 << 4) | ((x5 >> 1) & 0xF));
+ result[i + 3] = (byte)((x5 << 7) | ((x6 << 2) & 0x7C) | ((x7 >> 3) & 0x03));
+ result[i + 4] = (byte)((x7 << 5) | (x8 & 0x1F));
+ }
+
+ switch (tailLength)
+ {
+ case 4:
+ x1 = InvAlphabet[data[srcInd++]];
+ x2 = InvAlphabet[data[srcInd++]];
+ result[i] = (byte)((x1 << 3) | ((x2 >> 2) & 0x07));
+ break;
+ case 3:
+ x1 = InvAlphabet[data[srcInd++]];
+ x2 = InvAlphabet[data[srcInd++]];
+ x3 = InvAlphabet[data[srcInd++]];
+ x4 = InvAlphabet[data[srcInd++]];
+
+ result[i] = (byte)((x1 << 3) | ((x2 >> 2) & 0x07));
+ result[i + 1] = (byte)((x2 << 6) | ((x3 << 1) & 0x3E) | ((x4 >> 4) & 0x01));
+ break;
+ case 2:
+ x1 = InvAlphabet[data[srcInd++]];
+ x2 = InvAlphabet[data[srcInd++]];
+ x3 = InvAlphabet[data[srcInd++]];
+ x4 = InvAlphabet[data[srcInd++]];
+ x5 = InvAlphabet[data[srcInd++]];
+
+ result[i] = (byte)((x1 << 3) | ((x2 >> 2) & 0x07));
+ result[i + 1] = (byte)((x2 << 6) | ((x3 << 1) & 0x3E) | ((x4 >> 4) & 0x01));
+ result[i + 2] = (byte)((x4 << 4) | ((x5 >> 1) & 0xF));
+ break;
+ case 1:
+ x1 = InvAlphabet[data[srcInd++]];
+ x2 = InvAlphabet[data[srcInd++]];
+ x3 = InvAlphabet[data[srcInd++]];
+ x4 = InvAlphabet[data[srcInd++]];
+ x5 = InvAlphabet[data[srcInd++]];
+ x6 = InvAlphabet[data[srcInd++]];
+ x7 = InvAlphabet[data[srcInd++]];
+
+ result[i] = (byte)((x1 << 3) | ((x2 >> 2) & 0x07));
+ result[i + 1] = (byte)((x2 << 6) | ((x3 << 1) & 0x3E) | ((x4 >> 4) & 0x01));
+ result[i + 2] = (byte)((x4 << 4) | ((x5 >> 1) & 0xF));
+ result[i + 3] = (byte)((x5 << 7) | ((x6 << 2) & 0x7C) | ((x7 >> 3) & 0x03));
+ break;
+ }
+
+ return result;
+ }
+ }
+ }
+}
diff --git a/Assets/Scripts/BaseNcoding/Base32.cs.meta b/Assets/Scripts/BaseNcoding/Base32.cs.meta
new file mode 100644
index 0000000..b799a44
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding/Base32.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 126c83fbe81b32444ade8272d29789b1
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/BaseNcoding/Base64.cs b/Assets/Scripts/BaseNcoding/Base64.cs
new file mode 100644
index 0000000..302be4f
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding/Base64.cs
@@ -0,0 +1,170 @@
+using System;
+using System.Text;
+
+namespace BaseNcoding
+{
+ public class Base64 : Base
+ {
+ public const string DefaultAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ public const char DefaultSpecial = '=';
+
+ public override bool HasSpecial => true;
+
+ public Base64(string alphabet = DefaultAlphabet, char special = DefaultSpecial,
+ Encoding textEncoding = null, bool parallel = false)
+ : base(64, alphabet, special, textEncoding, parallel)
+ {
+ }
+
+ public override string Encode(byte[] data)
+ {
+ int resultLength = (data.Length + 2) / 3 * 4;
+ char[] result = new char[resultLength];
+
+ int length3 = data.Length / 3;
+ if (!Parallel)
+ {
+ EncodeBlock(data, result, 0, length3);
+ }
+ else
+ {
+ int processorCount = Math.Min(length3, Environment.ProcessorCount);
+ System.Threading.Tasks.Parallel.For(0, processorCount, i =>
+ {
+ int beginInd = i * length3 / processorCount;
+ int endInd = (i + 1) * length3 / processorCount;
+ EncodeBlock(data, result, beginInd, endInd);
+ });
+ }
+
+ int ind;
+ int x1, x2;
+ int srcInd, dstInd;
+ switch (data.Length - length3 * 3)
+ {
+ case 1:
+ ind = length3;
+ srcInd = ind * 3;
+ dstInd = ind * 4;
+ x1 = data[srcInd];
+ result[dstInd] = Alphabet[x1 >> 2];
+ result[dstInd + 1] = Alphabet[(x1 << 4) & 0x30];
+ result[dstInd + 2] = Special;
+ result[dstInd + 3] = Special;
+ break;
+ case 2:
+ ind = length3;
+ srcInd = ind * 3;
+ dstInd = ind * 4;
+ x1 = data[srcInd];
+ x2 = data[srcInd + 1];
+ result[dstInd] = Alphabet[x1 >> 2];
+ result[dstInd + 1] = Alphabet[((x1 << 4) & 0x30) | (x2 >> 4)];
+ result[dstInd + 2] = Alphabet[(x2 << 2) & 0x3C];
+ result[dstInd + 3] = Special;
+ break;
+ }
+
+ return new string(result);
+ }
+
+ public override byte[] Decode(string data)
+ {
+ unchecked
+ {
+ if (string.IsNullOrEmpty(data))
+ return new byte[0];
+
+ int lastSpecialInd = data.Length;
+ while (data[lastSpecialInd - 1] == Special)
+ lastSpecialInd--;
+ int tailLength = data.Length - lastSpecialInd;
+
+ int resultLength = (data.Length + 3) / 4 * 3 - tailLength;
+ byte[] result = new byte[resultLength];
+
+ int length4 = (data.Length - tailLength) / 4;
+ if (!Parallel)
+ {
+ DecodeBlock(data, result, 0, length4);
+ }
+ else
+ {
+ int processorCount = Math.Min(length4, Environment.ProcessorCount);
+ System.Threading.Tasks.Parallel.For(0, processorCount, i =>
+ {
+ int beginInd = i * length4 / processorCount;
+ int endInd = (i + 1) * length4 / processorCount;
+ DecodeBlock(data, result, beginInd, endInd);
+ });
+ }
+
+ int ind;
+ int x1, x2, x3;
+ int srcInd, dstInd;
+ switch (tailLength)
+ {
+ case 2:
+ ind = length4;
+ srcInd = ind * 4;
+ dstInd = ind * 3;
+ x1 = InvAlphabet[data[srcInd]];
+ x2 = InvAlphabet[data[srcInd + 1]];
+ result[dstInd] = (byte)((x1 << 2) | ((x2 >> 4) & 0x3));
+ break;
+ case 1:
+ ind = length4;
+ srcInd = ind * 4;
+ dstInd = ind * 3;
+ x1 = InvAlphabet[data[srcInd]];
+ x2 = InvAlphabet[data[srcInd + 1]];
+ x3 = InvAlphabet[data[srcInd + 2]];
+ result[dstInd] = (byte)((x1 << 2) | ((x2 >> 4) & 0x3));
+ result[dstInd + 1] = (byte)((x2 << 4) | ((x3 >> 2) & 0xF));
+ break;
+ }
+
+ return result;
+ }
+ }
+
+ private void EncodeBlock(byte[] src, char[] dst, int beginInd, int endInd)
+ {
+ for (int ind = beginInd; ind < endInd; ind++)
+ {
+ int srcInd = ind * 3;
+ int dstInd = ind * 4;
+
+ byte x1 = src[srcInd];
+ byte x2 = src[srcInd + 1];
+ byte x3 = src[srcInd + 2];
+
+ dst[dstInd] = Alphabet[x1 >> 2];
+ dst[dstInd + 1] = Alphabet[((x1 << 4) & 0x30) | (x2 >> 4)];
+ dst[dstInd + 2] = Alphabet[((x2 << 2) & 0x3C) | (x3 >> 6)];
+ dst[dstInd + 3] = Alphabet[x3 & 0x3F];
+ }
+ }
+
+ private void DecodeBlock(string src, byte[] dst, int beginInd, int endInd)
+ {
+ unchecked
+ {
+ for (int ind = beginInd; ind < endInd; ind++)
+ {
+ int srcInd = ind * 4;
+ int dstInd = ind * 3;
+
+ int x1 = InvAlphabet[src[srcInd]];
+ int x2 = InvAlphabet[src[srcInd + 1]];
+ int x3 = InvAlphabet[src[srcInd + 2]];
+ int x4 = InvAlphabet[src[srcInd + 3]];
+
+ dst[dstInd] = (byte)((x1 << 2) | ((x2 >> 4) & 0x3));
+ dst[dstInd + 1] = (byte)((x2 << 4) | ((x3 >> 2) & 0xF));
+ dst[dstInd + 2] = (byte)((x3 << 6) | (x4 & 0x3F));
+ }
+ }
+ }
+ }
+}
diff --git a/Assets/Scripts/BaseNcoding/Base64.cs.meta b/Assets/Scripts/BaseNcoding/Base64.cs.meta
new file mode 100644
index 0000000..a866f2e
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding/Base64.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b591d6746a6fd9b45a0174c0c22d292b
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/BaseNcoding/Base85.cs b/Assets/Scripts/BaseNcoding/Base85.cs
new file mode 100644
index 0000000..ce385ae
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding/Base85.cs
@@ -0,0 +1,181 @@
+using System;
+using System.IO;
+using System.Text;
+
+namespace BaseNcoding
+{
+ public class Base85 : Base
+ {
+ public const string DefaultAlphabet = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstu";
+ public const char DefaultSpecial = (char)0;
+ private static readonly uint[] Pow85 = { 85 * 85 * 85 * 85, 85 * 85 * 85, 85 * 85, 85, 1 };
+
+ public const string Prefix = "<~";
+ public const string Postfix = "~>";
+
+ public override bool HasSpecial => false;
+
+ public bool PrefixPostfix { get; set; }
+
+ public Base85(string alphabet = DefaultAlphabet, char special = DefaultSpecial, bool prefixPostfix = false, Encoding textEncoding = null)
+ : base(85, alphabet, special, textEncoding)
+ {
+ PrefixPostfix = prefixPostfix;
+ BlockBitsCount = 32;
+ BlockCharsCount = 5;
+ }
+
+ public override string Encode(byte[] data)
+ {
+ unchecked
+ {
+ byte[] encodedBlock = new byte[5];
+ int decodedBlockLength = 4;
+ int resultLength = data.Length * (encodedBlock.Length / decodedBlockLength);
+ if (PrefixPostfix)
+ resultLength += Prefix.Length + Postfix.Length;
+ char[] result = new char[resultLength];
+ int resultInd = 0;
+
+ if (PrefixPostfix)
+ CopyString(Prefix, result, ref resultInd);
+
+ int count = 0;
+ uint tuple = 0;
+ foreach (byte b in data)
+ {
+ if (count >= decodedBlockLength - 1)
+ {
+ tuple |= b;
+ if (tuple == 0)
+ result[resultInd++] = 'z';
+ else
+ EncodeBlock(encodedBlock.Length, result, ref resultInd, encodedBlock, tuple);
+ tuple = 0;
+ count = 0;
+ }
+ else
+ {
+ tuple |= (uint)(b << (24 - count * 8));
+ count++;
+ }
+ }
+
+ if (count > 0)
+ EncodeBlock(count + 1, result, ref resultInd, encodedBlock, tuple);
+
+ if (PrefixPostfix)
+ CopyString(Postfix, result, ref resultInd);
+
+ return new string(result);
+ }
+ }
+
+ public override byte[] Decode(string data)
+ {
+ unchecked
+ {
+ string dataWithoutPrefixPostfix = data;
+ if (PrefixPostfix)
+ {
+ if (!dataWithoutPrefixPostfix.StartsWith(Prefix) || !dataWithoutPrefixPostfix.EndsWith(Postfix))
+ {
+ throw new Exception("ASCII85 encoded data should begin with '" + Prefix + "' and end with '" + Postfix + "'");
+ }
+ dataWithoutPrefixPostfix = dataWithoutPrefixPostfix.Substring(Prefix.Length, dataWithoutPrefixPostfix.Length - Prefix.Length - Postfix.Length);
+ }
+
+ MemoryStream ms = new MemoryStream();
+ int count = 0;
+
+ uint tuple = 0;
+ int encodedBlockLength = 5;
+ byte[] decodedBlock = new byte[4];
+ foreach (char c in dataWithoutPrefixPostfix)
+ {
+ bool processChar;
+ switch (c)
+ {
+ case 'z':
+ if (count != 0)
+ {
+ throw new Exception("The character 'z' is invalid inside an ASCII85 block.");
+ }
+ decodedBlock[0] = 0;
+ decodedBlock[1] = 0;
+ decodedBlock[2] = 0;
+ decodedBlock[3] = 0;
+ ms.Write(decodedBlock, 0, decodedBlock.Length);
+ processChar = false;
+ break;
+ default:
+ processChar = true;
+ break;
+ }
+
+ if (processChar)
+ {
+ tuple += (uint)InvAlphabet[c] * Pow85[count];
+ count++;
+ if (count == encodedBlockLength)
+ {
+ DecodeBlock(decodedBlock.Length, decodedBlock, tuple);
+ ms.Write(decodedBlock, 0, decodedBlock.Length);
+ tuple = 0;
+ count = 0;
+ }
+ }
+ }
+
+ if (count != 0)
+ {
+ if (count == 1)
+ {
+ throw new Exception("The last block of ASCII85 data cannot be a single byte.");
+ }
+ count--;
+ tuple += Pow85[count];
+ DecodeBlock(count, decodedBlock, tuple);
+ for (int i = 0; i < count; i++)
+ {
+ ms.WriteByte(decodedBlock[i]);
+ }
+ }
+
+ return ms.ToArray();
+ }
+ }
+
+ private static void CopyString(string source, char[] dest, ref int destInd)
+ {
+ for (int i = 0; i < source.Length; i++)
+ dest[destInd++] = source[i];
+ }
+
+ private void EncodeBlock(int count, char[] result, ref int resultInd, byte[] encodedBlock, uint tuple)
+ {
+ unchecked
+ {
+ for (int i = encodedBlock.Length - 1; i >= 0; i--)
+ {
+ uint quotient = tuple % 85;
+ uint remainder = tuple - quotient * 85;
+ tuple = quotient;
+ encodedBlock[i] = (byte)remainder;
+ }
+
+ for (int i = 0; i < count; i++)
+ result[resultInd++] = Alphabet[encodedBlock[i]];
+ }
+ }
+
+ private void DecodeBlock(int bytes, byte[] decodedBlock, uint tuple)
+ {
+ unchecked
+ {
+ for (int i = 0; i < bytes; i++)
+ decodedBlock[i] = (byte)(tuple >> 24 - i * 8);
+ }
+ }
+ }
+}
diff --git a/Assets/Scripts/BaseNcoding/Base85.cs.meta b/Assets/Scripts/BaseNcoding/Base85.cs.meta
new file mode 100644
index 0000000..a3cfa13
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding/Base85.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bb00dc9d3e90a49439d967614c88ded8
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/BaseNcoding/Base91.cs b/Assets/Scripts/BaseNcoding/Base91.cs
new file mode 100644
index 0000000..e1d1a8d
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding/Base91.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BaseNcoding
+{
+ public class Base91 : Base
+ {
+ public const string DefaultAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~\"";
+ public const char DefaultSpecial = (char)0;
+
+ public override bool HasSpecial => false;
+
+ public Base91(string alphabet = DefaultAlphabet, char special = DefaultSpecial, Encoding textEncoding = null)
+ : base(91, alphabet, special, textEncoding)
+ {
+ BlockBitsCount = 13;
+ BlockCharsCount = 2;
+ }
+
+ public override string Encode(byte[] data)
+ {
+ StringBuilder result = new StringBuilder(data.Length);
+
+ int ebq = 0, en = 0;
+ for (int i = 0; i < data.Length; ++i)
+ {
+ ebq |= (data[i] & 255) << en;
+ en += 8;
+ if (en > 13)
+ {
+ int ev = ebq & 8191;
+
+ if (ev > 88)
+ {
+ ebq >>= 13;
+ en -= 13;
+ }
+ else
+ {
+ ev = ebq & 16383;
+ ebq >>= 14;
+ en -= 14;
+ }
+
+ int quotient = Math.DivRem(ev, 91, out int remainder);
+ result.Append(Alphabet[remainder]);
+ result.Append(Alphabet[quotient]);
+ }
+ }
+
+ if (en > 0)
+ {
+ int quotient = Math.DivRem(ebq, 91, out int remainder);
+ result.Append(Alphabet[remainder]);
+ if (en > 7 || ebq > 90)
+ result.Append(Alphabet[quotient]);
+ }
+
+ return result.ToString();
+ }
+
+ public override byte[] Decode(string data)
+ {
+ unchecked
+ {
+ int dbq = 0, dn = 0, dv = -1;
+
+ List result = new List(data.Length);
+ for (int i = 0; i < data.Length; ++i)
+ {
+ if (InvAlphabet[data[i]] == -1)
+ continue;
+ if (dv == -1)
+ dv = InvAlphabet[data[i]];
+ else
+ {
+ dv += InvAlphabet[data[i]] * 91;
+ dbq |= dv << dn;
+ dn += (dv & 8191) > 88 ? 13 : 14;
+ do
+ {
+ result.Add((byte)dbq);
+ dbq >>= 8;
+ dn -= 8;
+ }
+ while (dn > 7);
+ dv = -1;
+ }
+ }
+
+ if (dv != -1)
+ result.Add((byte)(dbq | dv << dn));
+
+ return result.ToArray();
+ }
+ }
+ }
+}
diff --git a/Assets/Scripts/BaseNcoding/Base91.cs.meta b/Assets/Scripts/BaseNcoding/Base91.cs.meta
new file mode 100644
index 0000000..b9ab053
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding/Base91.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 445180477b0318d48b58549426fd8ba9
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/BaseNcoding/BaseBigN.cs b/Assets/Scripts/BaseNcoding/BaseBigN.cs
new file mode 100644
index 0000000..a862647
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding/BaseBigN.cs
@@ -0,0 +1,261 @@
+using System;
+using System.Numerics;
+using System.Text;
+
+namespace BaseNcoding
+{
+ public class BaseBigN : Base
+ {
+ private BigInteger[] _powN;
+
+ public bool ReverseOrder { get; }
+
+ public uint BlockMaxBitsCount { get; }
+
+ public bool MaxCompression { get; }
+
+ public override bool HasSpecial => false;
+
+ public BaseBigN(string alphabet, uint blockMaxBitsCount = 64,
+ Encoding encoding = null, bool reverseOrder = false, bool parallel = false,
+ bool maxCompression = false)
+ : base((uint)alphabet.Length, alphabet, '\0', encoding, parallel)
+ {
+ BlockMaxBitsCount = blockMaxBitsCount;
+ BlockBitsCount = GetOptimalBitsCount(CharsCount, out var charsCountInBits, BlockMaxBitsCount, 2);
+ BlockCharsCount = (int)charsCountInBits;
+
+ PreparePowN(BlockCharsCount);
+
+ ReverseOrder = reverseOrder;
+ MaxCompression = maxCompression;
+ }
+
+ public override string Encode(byte[] data)
+ {
+ if (data == null || data.Length == 0)
+ return "";
+
+ int blockBitsCount, blockCharsCount;
+ if (!MaxCompression)
+ {
+ blockBitsCount = BlockBitsCount;
+ blockCharsCount = BlockCharsCount;
+ }
+ else
+ {
+ blockBitsCount = data.Length * 8;
+ blockCharsCount = (int)Math.Ceiling(blockBitsCount * Math.Log(2, Alphabet.Length));
+ PreparePowN(blockCharsCount);
+ }
+
+ int data8 = data.Length * 8;
+ int mainBitsLength = data8 / blockBitsCount * blockBitsCount;
+ int tailBitsLength = data8 - mainBitsLength;
+ int mainCharsCount = mainBitsLength * blockCharsCount / blockBitsCount;
+ int tailCharsCount = (tailBitsLength * blockCharsCount + blockBitsCount - 1) / blockBitsCount;
+ int totalCharsCount = mainCharsCount + tailCharsCount;
+ int iterationCount = mainCharsCount / blockCharsCount;
+
+ var result = new char[totalCharsCount];
+
+ if (!Parallel)
+ EncodeBlock(data, result, 0, iterationCount, blockBitsCount, blockCharsCount);
+ else
+ {
+ int processorCount = Math.Min(iterationCount, Environment.ProcessorCount);
+ System.Threading.Tasks.Parallel.For(0, processorCount, i =>
+ {
+ int beginInd = i * iterationCount / processorCount;
+ int endInd = (i + 1) * iterationCount / processorCount;
+ EncodeBlock(data, result, beginInd, endInd, blockBitsCount, blockCharsCount);
+ });
+ }
+
+ if (tailBitsLength != 0)
+ {
+ BigInteger bits = GetBitsN(data, mainBitsLength, tailBitsLength);
+ BitsToChars(result, mainCharsCount, tailCharsCount, bits);
+ }
+
+ return new string(result);
+ }
+
+ public override byte[] Decode(string data)
+ {
+ if (string.IsNullOrEmpty(data))
+ return new byte[0];
+
+ int blockBitsCount, blockCharsCount;
+ if (!MaxCompression)
+ {
+ blockBitsCount = BlockBitsCount;
+ blockCharsCount = BlockCharsCount;
+ }
+ else
+ {
+ blockCharsCount = data.Length;
+ blockBitsCount = (int)(blockCharsCount / Math.Log(2, Alphabet.Length)) / 8 * 8;
+ PreparePowN(blockCharsCount);
+ }
+
+ int totalBitsLength = ((data.Length - 1) * blockBitsCount / blockCharsCount + 8) / 8 * 8;
+ int mainBitsLength = totalBitsLength / blockBitsCount * blockBitsCount;
+ int tailBitsLength = totalBitsLength - mainBitsLength;
+ int mainCharsCount = mainBitsLength * blockCharsCount / blockBitsCount;
+ int tailCharsCount = (tailBitsLength * blockCharsCount + blockBitsCount - 1) / blockBitsCount;
+ BigInteger tailBits = CharsToBits(data, mainCharsCount, tailCharsCount);
+ if (tailBits >> tailBitsLength != 0)
+ {
+ totalBitsLength += 8;
+ mainBitsLength = totalBitsLength / blockBitsCount * blockBitsCount;
+ tailBitsLength = totalBitsLength - mainBitsLength;
+ mainCharsCount = mainBitsLength * blockCharsCount / blockBitsCount;
+ tailCharsCount = (tailBitsLength * blockCharsCount + blockBitsCount - 1) / blockBitsCount;
+ }
+ int iterationCount = mainCharsCount / blockCharsCount;
+
+ byte[] result = new byte[totalBitsLength / 8];
+
+ if (!Parallel)
+ {
+ DecodeBlock(data, result, 0, iterationCount, blockBitsCount, blockCharsCount);
+ }
+ else
+ {
+ int processorCount = Math.Min(iterationCount, Environment.ProcessorCount);
+ System.Threading.Tasks.Parallel.For(0, processorCount, i =>
+ {
+ int beginInd = i * iterationCount / processorCount;
+ int endInd = (i + 1) * iterationCount / processorCount;
+ DecodeBlock(data, result, beginInd, endInd, blockBitsCount, blockCharsCount);
+ });
+ }
+
+ if (tailCharsCount != 0)
+ {
+ BigInteger bits = CharsToBits(data, mainCharsCount, tailCharsCount);
+ AddBitsN(result, bits, mainBitsLength, tailBitsLength);
+ }
+
+ return result;
+ }
+
+ private void EncodeBlock(byte[] src, char[] dst, int beginInd, int endInd, int blockBitsCount, int blockCharsCount)
+ {
+ for (int ind = beginInd; ind < endInd; ind++)
+ {
+ int charInd = ind * blockCharsCount;
+ int bitInd = ind * blockBitsCount;
+ BigInteger bits = GetBitsN(src, bitInd, blockBitsCount);
+ BitsToChars(dst, charInd, blockCharsCount, bits);
+ }
+ }
+
+ private void DecodeBlock(string src, byte[] dst, int beginInd, int endInd, int blockBitsCount, int blockCharsCount)
+ {
+ for (int ind = beginInd; ind < endInd; ind++)
+ {
+ int charInd = ind * blockCharsCount;
+ int bitInd = ind * blockBitsCount;
+ BigInteger bits = CharsToBits(src, charInd, blockCharsCount);
+ AddBitsN(dst, bits, bitInd, blockBitsCount);
+ }
+ }
+
+ private static BigInteger GetBitsN(byte[] data, int bitPos, int bitsCount)
+ {
+ BigInteger result = 0;
+
+ int currentBytePos = Math.DivRem(bitPos, 8, out int currentBitInBytePos);
+ int shift = 8 - currentBitInBytePos;
+ int xLength = Math.Min(bitsCount, shift);
+ if (xLength != 0)
+ {
+ result = new BigInteger((data[currentBytePos] >> shift - xLength) & ((1 << shift) - 1)) << bitsCount - xLength;
+
+ currentBytePos += Math.DivRem(currentBitInBytePos + xLength, 8, out currentBitInBytePos);
+
+ int x2Length = bitsCount - xLength;
+ if (x2Length > 8)
+ x2Length = 8;
+
+ while (x2Length > 0)
+ {
+ xLength += x2Length;
+ result |= (BigInteger)(data[currentBytePos] >> 8 - x2Length) << bitsCount - xLength;
+
+ currentBytePos += Math.DivRem(currentBitInBytePos + x2Length, 8, out currentBitInBytePos);
+
+ x2Length = bitsCount - xLength;
+ if (x2Length > 8)
+ x2Length = 8;
+ }
+ }
+
+ return result;
+ }
+
+ private static void AddBitsN(byte[] data, BigInteger value, int bitPos, int bitsCount)
+ {
+ int currentBytePos = Math.DivRem(bitPos, 8, out int currentBitInBytePos);
+
+ int shift = 8 - currentBitInBytePos;
+ int xLength = Math.Min(bitsCount, shift);
+ if (xLength != 0)
+ {
+ data[currentBytePos] |= (byte) ((byte) (value >> bitsCount - shift) & ((1 << shift) - 1));
+
+ currentBytePos += Math.DivRem(currentBitInBytePos + xLength, 8, out currentBitInBytePos);
+
+ int x2Length = bitsCount - xLength;
+ if (x2Length > 8)
+ x2Length = 8;
+
+ while (x2Length > 0)
+ {
+ xLength += x2Length;
+ var bitsCountMinusXLength = bitsCount - xLength;
+ data[currentBytePos] |= (byte)((value >> (bitsCountMinusXLength - 8 + x2Length)) & 0xFF);
+
+ currentBytePos += Math.DivRem(currentBitInBytePos + x2Length, 8, out currentBitInBytePos);
+
+ x2Length = bitsCountMinusXLength;
+ if (x2Length > 8)
+ x2Length = 8;
+ }
+ }
+ }
+
+ private void BitsToChars(char[] chars, int ind, int count, BigInteger block)
+ {
+ BigInteger quotient = block;
+ for (int i = 0; i < count; i++)
+ {
+ quotient = BigInteger.DivRem(quotient, CharsCount, out BigInteger remainder);
+ chars[ind + (!ReverseOrder ? i : count - 1 - i)] = Alphabet[(int)remainder];
+ }
+ }
+
+ private BigInteger CharsToBits(string data, int ind, int count)
+ {
+ BigInteger result = 0;
+ for (int i = 0; i < count; i++)
+ result += InvAlphabet[data[ind + (!ReverseOrder ? i : count - 1 - i)]] * _powN[_powN.Length - 1 - i];
+ return result;
+ }
+
+ private void PreparePowN(int blockCharsCount)
+ {
+ _powN = new BigInteger[blockCharsCount];
+ BigInteger pow = 1;
+ for (int i = 0; i < blockCharsCount - 1; i++)
+ {
+ _powN[blockCharsCount - 1 - i] = pow;
+ pow *= CharsCount;
+ }
+ if (blockCharsCount > 0)
+ _powN[0] = pow;
+ }
+ }
+}
diff --git a/Assets/Scripts/BaseNcoding/BaseBigN.cs.meta b/Assets/Scripts/BaseNcoding/BaseBigN.cs.meta
new file mode 100644
index 0000000..e383bc8
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding/BaseBigN.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0a06acee1a2bf3d4aae0b2a2b83cb5d4
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/BaseNcoding/BaseN.cs b/Assets/Scripts/BaseNcoding/BaseN.cs
new file mode 100644
index 0000000..6a1c011
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding/BaseN.cs
@@ -0,0 +1,228 @@
+using System;
+using System.Text;
+
+namespace BaseNcoding
+{
+ public class BaseN : Base
+ {
+ private readonly ulong[] _powN;
+
+ public uint BlockMaxBitsCount { get; }
+
+ public override bool HasSpecial => false;
+
+ public bool ReverseOrder { get; }
+
+ public BaseN(string alphabet, uint blockMaxBitsCount = 32,
+ Encoding encoding = null, bool reverseOrder = false, bool parallel = false)
+ : base((uint)alphabet.Length, alphabet, '\0', encoding, parallel)
+ {
+ BlockMaxBitsCount = blockMaxBitsCount;
+ BlockBitsCount = GetOptimalBitsCount(CharsCount, out var charsCountInBits, blockMaxBitsCount);
+ BlockCharsCount = (int)charsCountInBits;
+ _powN = new ulong[BlockCharsCount];
+ ulong pow = 1;
+ for (int i = 0; i < BlockCharsCount - 1; i++)
+ {
+ _powN[BlockCharsCount - 1 - i] = pow;
+ pow *= CharsCount;
+ }
+ _powN[0] = pow;
+ ReverseOrder = reverseOrder;
+ }
+
+ public override string Encode(byte[] data)
+ {
+ if (data == null || data.Length == 0)
+ return "";
+
+ int mainBitsLength = data.Length * 8 / BlockBitsCount * BlockBitsCount;
+ int tailBitsLength = data.Length * 8 - mainBitsLength;
+ int mainCharsCount = mainBitsLength * BlockCharsCount / BlockBitsCount;
+ int tailCharsCount = (tailBitsLength * BlockCharsCount + BlockBitsCount - 1) / BlockBitsCount;
+ int totalCharsCount = mainCharsCount + tailCharsCount;
+ int iterationCount = mainCharsCount / BlockCharsCount;
+
+ var result = new char[totalCharsCount];
+
+ if (!Parallel)
+ {
+ EncodeBlock(data, result, 0, iterationCount);
+ }
+ else
+ {
+ int processorCount = Math.Min(iterationCount, Environment.ProcessorCount);
+ System.Threading.Tasks.Parallel.For(0, processorCount, i =>
+ {
+ int beginInd = i * iterationCount / processorCount;
+ int endInd = (i + 1) * iterationCount / processorCount;
+ EncodeBlock(data, result, beginInd, endInd);
+ });
+ }
+
+ if (tailBitsLength != 0)
+ {
+ ulong bits = GetBits64(data, mainBitsLength, tailBitsLength);
+ BitsToChars(result, mainCharsCount, tailCharsCount, bits);
+ }
+
+ return new string(result);
+ }
+
+ public override byte[] Decode(string data)
+ {
+ if (string.IsNullOrEmpty(data))
+ return new byte[0];
+
+ int totalBitsLength = ((data.Length - 1) * BlockBitsCount / BlockCharsCount + 8) / 8 * 8;
+ int mainBitsLength = totalBitsLength / BlockBitsCount * BlockBitsCount;
+ int tailBitsLength = totalBitsLength - mainBitsLength;
+ int mainCharsCount = mainBitsLength * BlockCharsCount / BlockBitsCount;
+ int tailCharsCount = (tailBitsLength * BlockCharsCount + BlockBitsCount - 1) / BlockBitsCount;
+ ulong tailBits = CharsToBits(data, mainCharsCount, tailCharsCount);
+ if (tailBits >> tailBitsLength != 0)
+ {
+ totalBitsLength += 8;
+ mainBitsLength = totalBitsLength / BlockBitsCount * BlockBitsCount;
+ tailBitsLength = totalBitsLength - mainBitsLength;
+ mainCharsCount = mainBitsLength * BlockCharsCount / BlockBitsCount;
+ tailCharsCount = (tailBitsLength * BlockCharsCount + BlockBitsCount - 1) / BlockBitsCount;
+ }
+ int iterationCount = mainCharsCount / BlockCharsCount;
+
+ byte[] result = new byte[totalBitsLength / 8];
+
+ if (!Parallel)
+ {
+ DecodeBlock(data, result, 0, iterationCount);
+ }
+ else
+ {
+ int processorCount = Math.Min(iterationCount, Environment.ProcessorCount);
+ System.Threading.Tasks.Parallel.For(0, processorCount, i =>
+ {
+ int beginInd = i * iterationCount / processorCount;
+ int endInd = (i + 1) * iterationCount / processorCount;
+ DecodeBlock(data, result, beginInd, endInd);
+ });
+ }
+
+ if (tailCharsCount != 0)
+ {
+ ulong bits = CharsToBits(data, mainCharsCount, tailCharsCount);
+ AddBits64(result, bits, mainBitsLength, tailBitsLength);
+ }
+
+ return result;
+ }
+
+ private void EncodeBlock(byte[] src, char[] dst, int beginInd, int endInd)
+ {
+ for (int ind = beginInd; ind < endInd; ind++)
+ {
+ int charInd = ind * BlockCharsCount;
+ int bitInd = ind * BlockBitsCount;
+ ulong bits = GetBits64(src, bitInd, BlockBitsCount);
+ BitsToChars(dst, charInd, BlockCharsCount, bits);
+ }
+ }
+
+ private void DecodeBlock(string src, byte[] dst, int beginInd, int endInd)
+ {
+ for (int ind = beginInd; ind < endInd; ind++)
+ {
+ int charInd = ind * BlockCharsCount;
+ int bitInd = ind * BlockBitsCount;
+ ulong bits = CharsToBits(src, charInd, BlockCharsCount);
+ AddBits64(dst, bits, bitInd, BlockBitsCount);
+ }
+ }
+
+ private static ulong GetBits64(byte[] data, int bitPos, int bitsCount)
+ {
+ ulong result = 0;
+
+ int currentBytePos = Math.DivRem(bitPos, 8, out int currentBitInBytePos);
+
+ int xLength = Math.Min(bitsCount, 8 - currentBitInBytePos);
+ if (xLength != 0)
+ {
+ result = ((ulong)data[currentBytePos] << 56 + currentBitInBytePos) >> 64 - xLength << bitsCount - xLength;
+
+ currentBytePos += Math.DivRem(currentBitInBytePos + xLength, 8, out currentBitInBytePos);
+
+ int x2Length = bitsCount - xLength;
+ if (x2Length > 8)
+ x2Length = 8;
+
+ while (x2Length > 0)
+ {
+ xLength += x2Length;
+ result |= (ulong)data[currentBytePos] >> 8 - x2Length << bitsCount - xLength;
+
+ currentBytePos += Math.DivRem(currentBitInBytePos + x2Length, 8, out currentBitInBytePos);
+
+ x2Length = bitsCount - xLength;
+ if (x2Length > 8)
+ x2Length = 8;
+ }
+ }
+
+ return result;
+ }
+
+ private static void AddBits64(byte[] data, ulong value, int bitPos, int bitsCount)
+ {
+ unchecked
+ {
+ int currentBytePos = Math.DivRem(bitPos, 8, out int currentBitInBytePos);
+
+ int xLength = Math.Min(bitsCount, 8 - currentBitInBytePos);
+ if (xLength != 0)
+ {
+ byte x1 = (byte)(value << 64 - bitsCount >> 56 + currentBitInBytePos);
+ data[currentBytePos] |= x1;
+
+ currentBytePos += Math.DivRem(currentBitInBytePos + xLength, 8, out currentBitInBytePos);
+
+ int x2Length = bitsCount - xLength;
+ if (x2Length > 8)
+ x2Length = 8;
+
+ while (x2Length > 0)
+ {
+ xLength += x2Length;
+ byte x2 = (byte)(value >> bitsCount - xLength << 8 - x2Length);
+ data[currentBytePos] |= x2;
+
+ currentBytePos += Math.DivRem(currentBitInBytePos + x2Length, 8, out currentBitInBytePos);
+
+ x2Length = bitsCount - xLength;
+ if (x2Length > 8)
+ x2Length = 8;
+ }
+ }
+ }
+ }
+
+ private void BitsToChars(char[] chars, int ind, int count, ulong block)
+ {
+ ulong result = block;
+ for (int i = 0; i < count; i++)
+ {
+ ulong quotient = result / CharsCount;
+ ulong remainder = result - quotient * CharsCount;
+ result = quotient;
+ chars[ind + (!ReverseOrder ? i : count - 1 - i)] = Alphabet[(int)remainder];
+ }
+ }
+
+ private ulong CharsToBits(string data, int ind, int count)
+ {
+ ulong result = 0;
+ for (int i = 0; i < count; i++)
+ result += (ulong)InvAlphabet[data[ind + (!ReverseOrder ? i : count - 1 - i)]] * _powN[BlockCharsCount - 1 - i];
+ return result;
+ }
+ }
+}
diff --git a/Assets/Scripts/BaseNcoding/BaseN.cs.meta b/Assets/Scripts/BaseNcoding/BaseN.cs.meta
new file mode 100644
index 0000000..4b0cada
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding/BaseN.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8d996e73fb18bfd45be33725dcf13786
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/BaseNcoding/StringGenerator.cs b/Assets/Scripts/BaseNcoding/StringGenerator.cs
new file mode 100644
index 0000000..339a396
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding/StringGenerator.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Text;
+
+namespace BaseNcoding
+{
+ public static class StringGenerator
+ {
+ private const string LettersAndDigits = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+ public static string GetAlphabet(int charsCount)
+ {
+ var result = new StringBuilder(charsCount);
+ int i = 0;
+ int count = 0;
+ do
+ {
+ char c = (char)i;
+ if (!char.IsControl(c) && !char.IsWhiteSpace(c))
+ {
+ result.Append(c);
+ count++;
+ }
+ i++;
+ }
+ while (count < charsCount);
+
+ return result.ToString();
+ }
+
+ public static string GetRandom(int size, bool onlyLettersAndDigits)
+ {
+ Random r = new Random();
+ if (onlyLettersAndDigits)
+ {
+ var result = new char[size];
+ for (int i = 0; i < size; i++)
+ result[i] = LettersAndDigits[r.Next(LettersAndDigits.Length)];
+ return new string(result);
+ }
+
+ var data = new byte[size];
+ for (int i = 0; i < size; i++)
+ data[i] = (byte) r.Next(32, 127);
+ var encoding = new ASCIIEncoding();
+ return encoding.GetString(data);
+ }
+ }
+}
diff --git a/Assets/Scripts/BaseNcoding/StringGenerator.cs.meta b/Assets/Scripts/BaseNcoding/StringGenerator.cs.meta
new file mode 100644
index 0000000..df242cc
--- /dev/null
+++ b/Assets/Scripts/BaseNcoding/StringGenerator.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b72d6d0bcd1a9e846ad04cc26014bbcd
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/LZ4.meta b/Assets/Scripts/LZ4.meta
new file mode 100644
index 0000000..50baab7
--- /dev/null
+++ b/Assets/Scripts/LZ4.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: dbb2fcf97a52a74408ada473a663544b
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/LZ4/LZ4Codec.Safe.cs b/Assets/Scripts/LZ4/LZ4Codec.Safe.cs
new file mode 100644
index 0000000..7b55e92
--- /dev/null
+++ b/Assets/Scripts/LZ4/LZ4Codec.Safe.cs
@@ -0,0 +1,757 @@
+#region license
+
+/*
+Copyright (c) 2013, Milosz Krajewski
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided
+that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this list of conditions
+ and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
+ and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#endregion
+
+using System;
+using System.Diagnostics;
+
+// ReSharper disable CheckNamespace
+// ReSharper disable InconsistentNaming
+
+namespace LZ4ps
+{
+ /// Safe LZ4 codec.
+ public static partial class LZ4Codec
+ {
+ #region Helper
+
+ // ReSharper disable UnusedParameter.Local
+
+ [Conditional("DEBUG")]
+ private static void Assert(bool condition, string errorMessage)
+ {
+ if (!condition) throw new ArgumentException(errorMessage);
+ Debug.Assert(condition, errorMessage);
+ }
+
+ // ReSharper restore UnusedParameter.Local
+
+ #endregion
+
+ #region Byte manipulation
+
+ // ReSharper disable RedundantCast
+
+ internal static void Poke2(byte[] buffer, int offset, ushort value)
+ {
+ buffer[offset] = (byte)value;
+ buffer[offset + 1] = (byte)(value >> 8);
+ }
+
+ internal static ushort Peek2(byte[] buffer, int offset)
+ {
+ // NOTE: It's faster than BitConverter.ToUInt16 (suprised? me too)
+ return (ushort)(((uint)buffer[offset]) | ((uint)buffer[offset + 1] << 8));
+ }
+
+ internal static uint Peek4(byte[] buffer, int offset)
+ {
+ // NOTE: It's faster than BitConverter.ToUInt32 (suprised? me too)
+ return
+ ((uint)buffer[offset]) |
+ ((uint)buffer[offset + 1] << 8) |
+ ((uint)buffer[offset + 2] << 16) |
+ ((uint)buffer[offset + 3] << 24);
+ }
+
+ private static uint Xor4(byte[] buffer, int offset1, int offset2)
+ {
+ // return Peek4(buffer, offset1) ^ Peek4(buffer, offset2);
+ var value1 =
+ ((uint)buffer[offset1]) |
+ ((uint)buffer[offset1 + 1] << 8) |
+ ((uint)buffer[offset1 + 2] << 16) |
+ ((uint)buffer[offset1 + 3] << 24);
+ var value2 =
+ ((uint)buffer[offset2]) |
+ ((uint)buffer[offset2 + 1] << 8) |
+ ((uint)buffer[offset2 + 2] << 16) |
+ ((uint)buffer[offset2 + 3] << 24);
+ return value1 ^ value2;
+ }
+
+ private static ulong Xor8(byte[] buffer, int offset1, int offset2)
+ {
+ // return Peek8(buffer, offset1) ^ Peek8(buffer, offset2);
+ var value1 =
+ ((ulong)buffer[offset1]) |
+ ((ulong)buffer[offset1 + 1] << 8) |
+ ((ulong)buffer[offset1 + 2] << 16) |
+ ((ulong)buffer[offset1 + 3] << 24) |
+ ((ulong)buffer[offset1 + 4] << 32) |
+ ((ulong)buffer[offset1 + 5] << 40) |
+ ((ulong)buffer[offset1 + 6] << 48) |
+ ((ulong)buffer[offset1 + 7] << 56);
+ var value2 =
+ ((ulong)buffer[offset2]) |
+ ((ulong)buffer[offset2 + 1] << 8) |
+ ((ulong)buffer[offset2 + 2] << 16) |
+ ((ulong)buffer[offset2 + 3] << 24) |
+ ((ulong)buffer[offset2 + 4] << 32) |
+ ((ulong)buffer[offset2 + 5] << 40) |
+ ((ulong)buffer[offset2 + 6] << 48) |
+ ((ulong)buffer[offset2 + 7] << 56);
+ return value1 ^ value2;
+ }
+
+ private static bool Equal2(byte[] buffer, int offset1, int offset2)
+ {
+ // return Peek2(buffer, offset1) == Peek2(buffer, offset2);
+ if (buffer[offset1] != buffer[offset2]) return false;
+ return buffer[offset1 + 1] == buffer[offset2 + 1];
+ }
+
+ private static bool Equal4(byte[] buffer, int offset1, int offset2)
+ {
+ // return Peek4(buffer, offset1) == Peek4(buffer, offset2);
+ if (buffer[offset1] != buffer[offset2]) return false;
+ if (buffer[offset1 + 1] != buffer[offset2 + 1]) return false;
+ if (buffer[offset1 + 2] != buffer[offset2 + 2]) return false;
+ return buffer[offset1 + 3] == buffer[offset2 + 3];
+ }
+
+ // ReSharper restore RedundantCast
+
+ #endregion
+
+ #region Byte block copy
+
+ private static void Copy4(byte[] buf, int src, int dst)
+ {
+ Assert(dst > src, "Copying backwards is not implemented");
+ buf[dst + 3] = buf[src + 3];
+ buf[dst + 2] = buf[src + 2];
+ buf[dst + 1] = buf[src + 1];
+ buf[dst] = buf[src];
+ }
+
+ private static void Copy8(byte[] buf, int src, int dst)
+ {
+ Assert(dst > src, "Copying backwards is not implemented");
+ buf[dst + 7] = buf[src + 7];
+ buf[dst + 6] = buf[src + 6];
+ buf[dst + 5] = buf[src + 5];
+ buf[dst + 4] = buf[src + 4];
+ buf[dst + 3] = buf[src + 3];
+ buf[dst + 2] = buf[src + 2];
+ buf[dst + 1] = buf[src + 1];
+ buf[dst] = buf[src];
+ }
+
+ private static void BlockCopy(byte[] src, int src_0, byte[] dst, int dst_0, int len)
+ {
+ Assert(src != dst, "BlockCopy does not handle copying to the same buffer");
+
+ if (len >= BLOCK_COPY_LIMIT)
+ {
+ Buffer.BlockCopy(src, src_0, dst, dst_0, len);
+ }
+ else
+ {
+ while (len >= 8)
+ {
+ dst[dst_0] = src[src_0];
+ dst[dst_0 + 1] = src[src_0 + 1];
+ dst[dst_0 + 2] = src[src_0 + 2];
+ dst[dst_0 + 3] = src[src_0 + 3];
+ dst[dst_0 + 4] = src[src_0 + 4];
+ dst[dst_0 + 5] = src[src_0 + 5];
+ dst[dst_0 + 6] = src[src_0 + 6];
+ dst[dst_0 + 7] = src[src_0 + 7];
+ len -= 8;
+ src_0 += 8;
+ dst_0 += 8;
+ }
+
+ while (len >= 4)
+ {
+ dst[dst_0] = src[src_0];
+ dst[dst_0 + 1] = src[src_0 + 1];
+ dst[dst_0 + 2] = src[src_0 + 2];
+ dst[dst_0 + 3] = src[src_0 + 3];
+ len -= 4;
+ src_0 += 4;
+ dst_0 += 4;
+ }
+
+ while (len-- > 0)
+ {
+ dst[dst_0++] = src[src_0++];
+ }
+ }
+ }
+
+ private static int WildCopy(byte[] src, int src_0, byte[] dst, int dst_0, int dst_end)
+ {
+ var len = dst_end - dst_0;
+
+ Assert(src != dst, "BlockCopy does not handle copying to the same buffer");
+ Assert(len > 0, "Length have to be greater than 0");
+
+ if (len >= BLOCK_COPY_LIMIT)
+ {
+ Buffer.BlockCopy(src, src_0, dst, dst_0, len);
+ }
+ else
+ {
+ // apparently (tested) this is an overkill
+ // it seems to be faster without this 8-byte loop
+ //while (len >= 8)
+ //{
+ // dst[dst_0] = src[src_0];
+ // dst[dst_0 + 1] = src[src_0 + 1];
+ // dst[dst_0 + 2] = src[src_0 + 2];
+ // dst[dst_0 + 3] = src[src_0 + 3];
+ // dst[dst_0 + 4] = src[src_0 + 4];
+ // dst[dst_0 + 5] = src[src_0 + 5];
+ // dst[dst_0 + 6] = src[src_0 + 6];
+ // dst[dst_0 + 7] = src[src_0 + 7];
+ // len -= 8; src_0 += 8; dst_0 += 8;
+ //}
+
+ while (len >= 4)
+ {
+ dst[dst_0] = src[src_0];
+ dst[dst_0 + 1] = src[src_0 + 1];
+ dst[dst_0 + 2] = src[src_0 + 2];
+ dst[dst_0 + 3] = src[src_0 + 3];
+ len -= 4;
+ src_0 += 4;
+ dst_0 += 4;
+ }
+
+ while (len-- > 0)
+ {
+ dst[dst_0++] = src[src_0++];
+ }
+ }
+
+ return len;
+ }
+
+ private static int SecureCopy(byte[] buffer, int src, int dst, int dst_end)
+ {
+ var diff = dst - src;
+ var length = dst_end - dst;
+ var len = length;
+
+ Assert(diff >= 4, "Target must be at least 4 bytes further than source");
+ Assert(BLOCK_COPY_LIMIT > 4, "This method requires BLOCK_COPY_LIMIT > 4");
+ Assert(len > 0, "Length have to be greater than 0");
+
+ if (diff >= BLOCK_COPY_LIMIT)
+ {
+ if (diff >= length)
+ {
+ Buffer.BlockCopy(buffer, src, buffer, dst, length);
+ return length; // done
+ }
+
+ do
+ {
+ Buffer.BlockCopy(buffer, src, buffer, dst, diff);
+ src += diff;
+ dst += diff;
+ len -= diff;
+ } while (len >= diff);
+ }
+
+ // apparently (tested) this is an overkill
+ // it seems to be faster without this 8-byte loop
+ //while (len >= 8)
+ //{
+ // buffer[dst] = buffer[src];
+ // buffer[dst + 1] = buffer[src + 1];
+ // buffer[dst + 2] = buffer[src + 2];
+ // buffer[dst + 3] = buffer[src + 3];
+ // buffer[dst + 4] = buffer[src + 4];
+ // buffer[dst + 5] = buffer[src + 5];
+ // buffer[dst + 6] = buffer[src + 6];
+ // buffer[dst + 7] = buffer[src + 7];
+ // dst += 8; src += 8; len -= 8;
+ //}
+
+ while (len >= 4)
+ {
+ buffer[dst] = buffer[src];
+ buffer[dst + 1] = buffer[src + 1];
+ buffer[dst + 2] = buffer[src + 2];
+ buffer[dst + 3] = buffer[src + 3];
+ dst += 4;
+ src += 4;
+ len -= 4;
+ }
+
+ while (len-- > 0)
+ {
+ buffer[dst++] = buffer[src++];
+ }
+
+ return length; // done
+ }
+
+ #endregion
+
+ #region Encode32
+
+ /// Encodes the specified input.
+ /// The input.
+ /// The input offset.
+ /// Length of the input.
+ /// The output.
+ /// The output offset.
+ /// Length of the output.
+ /// Number of bytes written.
+ public static int Encode32(
+ byte[] input,
+ int inputOffset,
+ int inputLength,
+ byte[] output,
+ int outputOffset,
+ int outputLength)
+ {
+ CheckArguments(
+ input, inputOffset, ref inputLength,
+ output, outputOffset, ref outputLength);
+ if (outputLength == 0) return 0;
+
+ if (inputLength < LZ4_64KLIMIT)
+ {
+ var hashTable = new ushort[HASH64K_TABLESIZE];
+ return LZ4_compress64kCtx_safe32(hashTable, input, output, inputOffset, outputOffset, inputLength, outputLength);
+ }
+ else
+ {
+ var hashTable = new int[HASH_TABLESIZE];
+ return LZ4_compressCtx_safe32(hashTable, input, output, inputOffset, outputOffset, inputLength, outputLength);
+ }
+ }
+
+ /// Encodes the specified input.
+ /// The input.
+ /// The input offset.
+ /// Length of the input.
+ /// Compressed buffer.
+ public static byte[] Encode32(byte[] input, int inputOffset, int inputLength)
+ {
+ if (inputLength < 0) inputLength = input.Length - inputOffset;
+
+ if (input == null) throw new ArgumentNullException("input");
+ if (inputOffset < 0 || inputOffset + inputLength > input.Length)
+ throw new ArgumentException("inputOffset and inputLength are invalid for given input");
+
+ var result = new byte[MaximumOutputLength(inputLength)];
+ var length = Encode32(input, inputOffset, inputLength, result, 0, result.Length);
+
+ if (length != result.Length)
+ {
+ if (length < 0)
+ throw new InvalidOperationException("Compression has been corrupted");
+ var buffer = new byte[length];
+ Buffer.BlockCopy(result, 0, buffer, 0, length);
+ return buffer;
+ }
+ return result;
+ }
+
+ #endregion
+
+ #region Encode64
+
+ /// Encodes the specified input.
+ /// The input.
+ /// The input offset.
+ /// Length of the input.
+ /// The output.
+ /// The output offset.
+ /// Length of the output.
+ /// Number of bytes written.
+ public static int Encode64(
+ byte[] input,
+ int inputOffset,
+ int inputLength,
+ byte[] output,
+ int outputOffset,
+ int outputLength)
+ {
+ CheckArguments(
+ input, inputOffset, ref inputLength,
+ output, outputOffset, ref outputLength);
+ if (outputLength == 0) return 0;
+
+ if (inputLength < LZ4_64KLIMIT)
+ {
+ var hashTable = new ushort[HASH64K_TABLESIZE];
+ return LZ4_compress64kCtx_safe64(hashTable, input, output, inputOffset, outputOffset, inputLength, outputLength);
+ }
+ else
+ {
+ var hashTable = new int[HASH_TABLESIZE];
+ return LZ4_compressCtx_safe64(hashTable, input, output, inputOffset, outputOffset, inputLength, outputLength);
+ }
+ }
+
+ /// Encodes the specified input.
+ /// The input.
+ /// The input offset.
+ /// Length of the input.
+ /// Compressed buffer.
+ public static byte[] Encode64(byte[] input, int inputOffset, int inputLength)
+ {
+ if (inputLength < 0) inputLength = input.Length - inputOffset;
+
+ if (input == null) throw new ArgumentNullException("input");
+ if (inputOffset < 0 || inputOffset + inputLength > input.Length)
+ throw new ArgumentException("inputOffset and inputLength are invalid for given input");
+
+ var result = new byte[MaximumOutputLength(inputLength)];
+ var length = Encode64(input, inputOffset, inputLength, result, 0, result.Length);
+
+ if (length != result.Length)
+ {
+ if (length < 0)
+ throw new InvalidOperationException("Compression has been corrupted");
+ var buffer = new byte[length];
+ Buffer.BlockCopy(result, 0, buffer, 0, length);
+ return buffer;
+ }
+ return result;
+ }
+
+ #endregion
+
+ #region Decode32
+
+ /// Decodes the specified input.
+ /// The input.
+ /// The input offset.
+ /// Length of the input.
+ /// The output.
+ /// The output offset.
+ /// Length of the output.
+ /// Set it to true if output length is known.
+ /// Number of bytes written.
+ public static int Decode32(
+ byte[] input,
+ int inputOffset,
+ int inputLength,
+ byte[] output,
+ int outputOffset,
+ int outputLength,
+ bool knownOutputLength)
+ {
+ CheckArguments(
+ input, inputOffset, ref inputLength,
+ output, outputOffset, ref outputLength);
+
+ if (outputLength == 0) return 0;
+
+ if (knownOutputLength)
+ {
+ var length = LZ4_uncompress_safe32(input, output, inputOffset, outputOffset, outputLength);
+ if (length != inputLength)
+ throw new ArgumentException("LZ4 block is corrupted, or invalid length has been given.");
+ return outputLength;
+ }
+ else
+ {
+ var length = LZ4_uncompress_unknownOutputSize_safe32(input, output, inputOffset, outputOffset, inputLength, outputLength);
+ if (length < 0)
+ throw new ArgumentException("LZ4 block is corrupted, or invalid length has been given.");
+ return length;
+ }
+ }
+
+ /// Decodes the specified input.
+ /// The input.
+ /// The input offset.
+ /// Length of the input.
+ /// Length of the output.
+ /// Decompressed buffer.
+ public static byte[] Decode32(byte[] input, int inputOffset, int inputLength, int outputLength)
+ {
+ if (inputLength < 0) inputLength = input.Length - inputOffset;
+
+ if (input == null) throw new ArgumentNullException("input");
+ if (inputOffset < 0 || inputOffset + inputLength > input.Length)
+ throw new ArgumentException("inputOffset and inputLength are invalid for given input");
+
+ var result = new byte[outputLength];
+ var length = Decode32(input, inputOffset, inputLength, result, 0, outputLength, true);
+ if (length != outputLength)
+ throw new ArgumentException("outputLength is not valid");
+ return result;
+ }
+
+ #endregion
+
+ #region Decode64
+
+ /// Decodes the specified input.
+ /// The input.
+ /// The input offset.
+ /// Length of the input.
+ /// The output.
+ /// The output offset.
+ /// Length of the output.
+ /// Set it to true if output length is known.
+ /// Number of bytes written.
+ public static int Decode64(
+ byte[] input,
+ int inputOffset,
+ int inputLength,
+ byte[] output,
+ int outputOffset,
+ int outputLength,
+ bool knownOutputLength)
+ {
+ CheckArguments(
+ input, inputOffset, ref inputLength,
+ output, outputOffset, ref outputLength);
+
+ if (outputLength == 0) return 0;
+
+ if (knownOutputLength)
+ {
+ var length = LZ4_uncompress_safe64(input, output, inputOffset, outputOffset, outputLength);
+ if (length != inputLength)
+ throw new ArgumentException("LZ4 block is corrupted, or invalid length has been given.");
+ return outputLength;
+ }
+ else
+ {
+ var length = LZ4_uncompress_unknownOutputSize_safe64(input, output, inputOffset, outputOffset, inputLength, outputLength);
+ if (length < 0)
+ throw new ArgumentException("LZ4 block is corrupted, or invalid length has been given.");
+ return length;
+ }
+ }
+
+ /// Decodes the specified input.
+ /// The input.
+ /// The input offset.
+ /// Length of the input.
+ /// Length of the output.
+ /// Decompressed buffer.
+ public static byte[] Decode64(byte[] input, int inputOffset, int inputLength, int outputLength)
+ {
+ if (inputLength < 0) inputLength = input.Length - inputOffset;
+
+ if (input == null) throw new ArgumentNullException("input");
+ if (inputOffset < 0 || inputOffset + inputLength > input.Length)
+ throw new ArgumentException("inputOffset and inputLength are invalid for given input");
+
+ var result = new byte[outputLength];
+ var length = Decode64(input, inputOffset, inputLength, result, 0, outputLength, true);
+ if (length != outputLength)
+ throw new ArgumentException("outputLength is not valid");
+ return result;
+ }
+
+ #endregion
+
+ #region HC utilities
+
+ // ReSharper disable InconsistentNaming
+
+ private class LZ4HC_Data_Structure
+ {
+ public byte[] src;
+ public int src_base;
+ public int src_end;
+ public int src_LASTLITERALS;
+ public byte[] dst;
+ public int dst_base;
+ public int dst_len;
+ public int dst_end;
+ public int[] hashTable;
+ public ushort[] chainTable;
+ public int nextToUpdate;
+ };
+
+ // ReSharper restore InconsistentNaming
+
+
+ private static LZ4HC_Data_Structure LZ4HC_Create(byte[] src, int src_0, int src_len, byte[] dst, int dst_0, int dst_len)
+ {
+ var hc4 = new LZ4HC_Data_Structure {
+ src = src,
+ src_base = src_0,
+ src_end = src_0 + src_len,
+ src_LASTLITERALS = (src_0 + src_len - LASTLITERALS),
+ dst = dst,
+ dst_base = dst_0,
+ dst_len = dst_len,
+ dst_end = dst_0 + dst_len,
+ hashTable = new int[HASHHC_TABLESIZE],
+ chainTable = new ushort[MAXD],
+ nextToUpdate = src_0 + 1,
+ };
+
+ var ct = hc4.chainTable;
+ for (var i = ct.Length - 1; i >= 0; i--) ct[i] = unchecked((ushort)-1);
+
+ return hc4;
+ }
+
+ #endregion
+
+ #region Encode32HC
+
+ private static int LZ4_compressHC_32(
+ byte[] input, int inputOffset, int inputLength,
+ byte[] output, int outputOffset, int outputLength)
+ {
+ return LZ4_compressHCCtx_32(
+ LZ4HC_Create(
+ input, inputOffset, inputLength, output, outputOffset, outputLength));
+ }
+
+ /// Encodes the specified input using HC codec.
+ /// The input.
+ /// The input offset.
+ /// Length of the input.
+ /// The output.
+ /// The output offset.
+ /// Length of the output.
+ /// Number of bytes written. NOTE: when output buffer is too small it returns negative value.
+ public static int Encode32HC(
+ byte[] input,
+ int inputOffset,
+ int inputLength,
+ byte[] output,
+ int outputOffset,
+ int outputLength)
+ {
+ if (inputLength == 0) return 0;
+
+ CheckArguments(
+ input, inputOffset, ref inputLength,
+ output, outputOffset, ref outputLength);
+
+ var length = LZ4_compressHC_32(input, inputOffset, inputLength, output, outputOffset, outputLength);
+ // NOTE: there is a potential problem here as original implementation returns 0 not -1
+ return length <= 0 ? -1 : length;
+ }
+
+ /// Encodes the specified input using HC codec.
+ /// The input.
+ /// The input offset.
+ /// Length of the input.
+ /// Buffer with compressed data (NOTE: it can be bigger than input).
+ public static byte[] Encode32HC(
+ byte[] input, int inputOffset, int inputLength)
+ {
+ if (inputLength == 0) return new byte[0];
+ var outputLength = MaximumOutputLength(inputLength);
+ var result = new byte[outputLength];
+ var length = Encode32HC(input, inputOffset, inputLength, result, 0, outputLength);
+
+ if (length < 0)
+ throw new ArgumentException("Provided data seems to be corrupted.");
+
+ if (length != outputLength)
+ {
+ var buffer = new byte[length];
+ Buffer.BlockCopy(result, 0, buffer, 0, length);
+ result = buffer;
+ }
+
+ return result;
+ }
+
+ #endregion
+
+ #region Encode64HC
+
+ private static int LZ4_compressHC_64(
+ byte[] input, int inputOffset, int inputLength,
+ byte[] output, int outputOffset, int outputLength)
+ {
+ return LZ4_compressHCCtx_64(
+ LZ4HC_Create(
+ input, inputOffset, inputLength, output, outputOffset, outputLength));
+ }
+
+ /// Encodes the specified input using HC codec.
+ /// The input.
+ /// The input offset.
+ /// Length of the input.
+ /// The output.
+ /// The output offset.
+ /// Length of the output.
+ /// Number of bytes written. NOTE: when output buffer is too small it returns negative value.
+ public static int Encode64HC(
+ byte[] input,
+ int inputOffset,
+ int inputLength,
+ byte[] output,
+ int outputOffset,
+ int outputLength)
+ {
+ if (inputLength == 0) return 0;
+
+ CheckArguments(
+ input, inputOffset, ref inputLength,
+ output, outputOffset, ref outputLength);
+
+ var length = LZ4_compressHC_64(input, inputOffset, inputLength, output, outputOffset, outputLength);
+ // NOTE: there is a potential problem here as original implementation returns 0 not -1
+ return length <= 0 ? -1 : length;
+ }
+
+ /// Encodes the specified input using HC codec.
+ /// The input.
+ /// The input offset.
+ /// Length of the input.
+ /// Buffer with compressed data (NOTE: it can be bigger than input).
+ public static byte[] Encode64HC(
+ byte[] input, int inputOffset, int inputLength)
+ {
+ if (inputLength == 0) return new byte[0];
+ var outputLength = MaximumOutputLength(inputLength);
+ var result = new byte[outputLength];
+ var length = Encode64HC(input, inputOffset, inputLength, result, 0, outputLength);
+
+ if (length < 0)
+ throw new ArgumentException("Provided data seems to be corrupted.");
+
+ if (length != outputLength)
+ {
+ var buffer = new byte[length];
+ Buffer.BlockCopy(result, 0, buffer, 0, length);
+ result = buffer;
+ }
+
+ return result;
+ }
+
+ #endregion
+ }
+}
+
+// ReSharper restore InconsistentNaming
+// ReSharper restore CheckNamespace
diff --git a/Assets/Scripts/LZ4/LZ4Codec.Safe.cs.meta b/Assets/Scripts/LZ4/LZ4Codec.Safe.cs.meta
new file mode 100644
index 0000000..c5fc009
--- /dev/null
+++ b/Assets/Scripts/LZ4/LZ4Codec.Safe.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a2f5d2c7e152d8f43ab710530107c9ff
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/LZ4/LZ4Codec.Safe32.Dirty.cs b/Assets/Scripts/LZ4/LZ4Codec.Safe32.Dirty.cs
new file mode 100644
index 0000000..85e7c49
--- /dev/null
+++ b/Assets/Scripts/LZ4/LZ4Codec.Safe32.Dirty.cs
@@ -0,0 +1,795 @@
+#region LZ4 original
+
+/*
+ LZ4 - Fast LZ compression algorithm
+ Copyright (C) 2011-2012, Yann Collet.
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ You can contact the author at :
+ - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
+ - LZ4 source repository : http://code.google.com/p/lz4/
+*/
+
+#endregion
+
+#region LZ4 port
+
+/*
+Copyright (c) 2013, Milosz Krajewski
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided
+that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this list of conditions
+ and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
+ and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#endregion
+
+// ReSharper disable CheckNamespace
+// ReSharper disable InconsistentNaming
+// ReSharper disable TooWideLocalVariableScope
+// ReSharper disable JoinDeclarationAndInitializer
+// ReSharper disable RedundantIfElseBlock
+
+namespace LZ4ps
+{
+ public static partial class LZ4Codec
+ {
+ #region LZ4_compressCtx
+
+ private static int LZ4_compressCtx_safe32(
+ int[] hash_table,
+ byte[] src,
+ byte[] dst,
+ int src_0,
+ int dst_0,
+ int src_len,
+ int dst_maxlen)
+ {
+ var debruijn32 = DEBRUIJN_TABLE_32;
+ int _i;
+
+ // ---- preprocessed source start here ----
+ // r93
+ var src_p = src_0;
+ var src_base = src_0;
+ var src_anchor = src_p;
+ var src_end = src_p + src_len;
+ var src_mflimit = src_end - MFLIMIT;
+
+ var dst_p = dst_0;
+ var dst_end = dst_p + dst_maxlen;
+
+ var src_LASTLITERALS = src_end - LASTLITERALS;
+ var src_LASTLITERALS_1 = src_LASTLITERALS - 1;
+
+ var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_32 - 1);
+ var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS);
+ var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS);
+
+ int length;
+
+ uint h, h_fwd;
+
+ // Init
+ if (src_len < MINLENGTH) goto _last_literals;
+
+ // First Byte
+ hash_table[(((Peek4(src, src_p)) * 2654435761u) >> HASH_ADJUST)] = (src_p - src_base);
+ src_p++;
+ h_fwd = (((Peek4(src, src_p)) * 2654435761u) >> HASH_ADJUST);
+
+ // Main Loop
+ while (true)
+ {
+ var findMatchAttempts = (1 << SKIPSTRENGTH) + 3;
+ var src_p_fwd = src_p;
+ int src_ref;
+ int dst_token;
+
+ // Find a match
+ do
+ {
+ h = h_fwd;
+ var step = findMatchAttempts++ >> SKIPSTRENGTH;
+ src_p = src_p_fwd;
+ src_p_fwd = src_p + step;
+
+ if (src_p_fwd > src_mflimit) goto _last_literals;
+
+ h_fwd = (((Peek4(src, src_p_fwd)) * 2654435761u) >> HASH_ADJUST);
+ src_ref = src_base + hash_table[h];
+ hash_table[h] = (src_p - src_base);
+ } while ((src_ref < src_p - MAX_DISTANCE) || (!Equal4(src, src_ref, src_p)));
+
+ // Catch up
+ while ((src_p > src_anchor) && (src_ref > src_0) && (src[src_p - 1] == src[src_ref - 1]))
+ {
+ src_p--;
+ src_ref--;
+ }
+
+ // Encode Literal length
+ length = (src_p - src_anchor);
+ dst_token = dst_p++;
+
+ if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3) return 0; // Check output limit
+
+ if (length >= RUN_MASK)
+ {
+ var len = length - RUN_MASK;
+ dst[dst_token] = (RUN_MASK << ML_BITS);
+ if (len > 254)
+ {
+ do
+ {
+ dst[dst_p++] = 255;
+ len -= 255;
+ } while (len > 254);
+ dst[dst_p++] = (byte)len;
+ BlockCopy(src, src_anchor, dst, dst_p, length);
+ dst_p += length;
+ goto _next_match;
+ }
+ else
+ dst[dst_p++] = (byte)len;
+ }
+ else
+ {
+ dst[dst_token] = (byte)(length << ML_BITS);
+ }
+
+ // Copy Literals
+ if (length > 0)
+ {
+ _i = dst_p + length;
+ WildCopy(src, src_anchor, dst, dst_p, _i);
+ dst_p = _i;
+ }
+
+ _next_match:
+ // Encode Offset
+ Poke2(dst, dst_p, (ushort)(src_p - src_ref));
+ dst_p += 2;
+
+ // Start Counting
+ src_p += MINMATCH;
+ src_ref += MINMATCH; // MinMatch already verified
+ src_anchor = src_p;
+
+ while (src_p < src_LASTLITERALS_STEPSIZE_1)
+ {
+ var diff = (int)Xor4(src, src_ref, src_p);
+ if (diff == 0)
+ {
+ src_p += STEPSIZE_32;
+ src_ref += STEPSIZE_32;
+ continue;
+ }
+ src_p += debruijn32[((uint)((diff) & -(diff)) * 0x077CB531u) >> 27];
+ goto _endCount;
+ }
+
+ if ((src_p < src_LASTLITERALS_1) && (Equal2(src, src_ref, src_p)))
+ {
+ src_p += 2;
+ src_ref += 2;
+ }
+ if ((src_p < src_LASTLITERALS) && (src[src_ref] == src[src_p])) src_p++;
+
+ _endCount:
+ // Encode MatchLength
+ length = (src_p - src_anchor);
+
+ if (dst_p + (length >> 8) > dst_LASTLITERALS_1) return 0; // Check output limit
+
+ if (length >= ML_MASK)
+ {
+ dst[dst_token] += ML_MASK;
+ length -= ML_MASK;
+ for (; length > 509; length -= 510)
+ {
+ dst[dst_p++] = 255;
+ dst[dst_p++] = 255;
+ }
+ if (length > 254)
+ {
+ length -= 255;
+ dst[dst_p++] = 255;
+ }
+ dst[dst_p++] = (byte)length;
+ }
+ else
+ {
+ dst[dst_token] += (byte)length;
+ }
+
+ // Test end of chunk
+ if (src_p > src_mflimit)
+ {
+ src_anchor = src_p;
+ break;
+ }
+
+ // Fill table
+ hash_table[(((Peek4(src, src_p - 2)) * 2654435761u) >> HASH_ADJUST)] = (src_p - 2 - src_base);
+
+ // Test next position
+
+ h = (((Peek4(src, src_p)) * 2654435761u) >> HASH_ADJUST);
+ src_ref = src_base + hash_table[h];
+ hash_table[h] = (src_p - src_base);
+
+ if ((src_ref > src_p - (MAX_DISTANCE + 1)) && (Equal4(src, src_ref, src_p)))
+ {
+ dst_token = dst_p++;
+ dst[dst_token] = 0;
+ goto _next_match;
+ }
+
+ // Prepare next loop
+ src_anchor = src_p++;
+ h_fwd = (((Peek4(src, src_p)) * 2654435761u) >> HASH_ADJUST);
+ }
+
+ _last_literals:
+ // Encode Last Literals
+ {
+ var lastRun = (src_end - src_anchor);
+
+ if (dst_p + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > dst_end) return 0;
+
+ if (lastRun >= RUN_MASK)
+ {
+ dst[dst_p++] = (RUN_MASK << ML_BITS);
+ lastRun -= RUN_MASK;
+ for (; lastRun > 254; lastRun -= 255) dst[dst_p++] = 255;
+ dst[dst_p++] = (byte)lastRun;
+ }
+ else dst[dst_p++] = (byte)(lastRun << ML_BITS);
+ BlockCopy(src, src_anchor, dst, dst_p, src_end - src_anchor);
+ dst_p += src_end - src_anchor;
+ }
+
+ // End
+ return ((dst_p) - dst_0);
+ }
+
+ #endregion
+
+ #region LZ4_compress64kCtx
+
+ private static int LZ4_compress64kCtx_safe32(
+ ushort[] hash_table,
+ byte[] src,
+ byte[] dst,
+ int src_0,
+ int dst_0,
+ int src_len,
+ int dst_maxlen)
+ {
+ var debruijn32 = DEBRUIJN_TABLE_32;
+ int _i;
+
+ // ---- preprocessed source start here ----
+ // r93
+ var src_p = src_0;
+ var src_anchor = src_p;
+ var src_base = src_p;
+ var src_end = src_p + src_len;
+ var src_mflimit = src_end - MFLIMIT;
+
+ var dst_p = dst_0;
+ var dst_end = dst_p + dst_maxlen;
+
+ var src_LASTLITERALS = src_end - LASTLITERALS;
+ var src_LASTLITERALS_1 = src_LASTLITERALS - 1;
+
+ var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_32 - 1);
+ var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS);
+ var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS);
+
+ int len, length;
+
+ uint h, h_fwd;
+
+ // Init
+ if (src_len < MINLENGTH) goto _last_literals;
+
+ // First Byte
+ src_p++;
+ h_fwd = (((Peek4(src, src_p)) * 2654435761u) >> HASH64K_ADJUST);
+
+ // Main Loop
+ while (true)
+ {
+ var findMatchAttempts = (1 << SKIPSTRENGTH) + 3;
+ var src_p_fwd = src_p;
+ int src_ref;
+ int dst_token;
+
+ // Find a match
+ do
+ {
+ h = h_fwd;
+ var step = findMatchAttempts++ >> SKIPSTRENGTH;
+ src_p = src_p_fwd;
+ src_p_fwd = src_p + step;
+
+ if (src_p_fwd > src_mflimit) goto _last_literals;
+
+ h_fwd = (((Peek4(src, src_p_fwd)) * 2654435761u) >> HASH64K_ADJUST);
+ src_ref = src_base + hash_table[h];
+ hash_table[h] = (ushort)(src_p - src_base);
+ } while (!Equal4(src, src_ref, src_p));
+
+ // Catch up
+ while ((src_p > src_anchor) && (src_ref > src_0) && (src[src_p - 1] == src[src_ref - 1]))
+ {
+ src_p--;
+ src_ref--;
+ }
+
+ // Encode Literal length
+ length = (src_p - src_anchor);
+ dst_token = dst_p++;
+
+ if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3) return 0; // Check output limit
+
+ if (length >= RUN_MASK)
+ {
+ len = length - RUN_MASK;
+ dst[dst_token] = (RUN_MASK << ML_BITS);
+ if (len > 254)
+ {
+ do
+ {
+ dst[dst_p++] = 255;
+ len -= 255;
+ } while (len > 254);
+ dst[dst_p++] = (byte)len;
+ BlockCopy(src, src_anchor, dst, dst_p, length);
+ dst_p += length;
+ goto _next_match;
+ }
+ else
+ {
+ dst[dst_p++] = (byte)len;
+ }
+ }
+ else
+ {
+ dst[dst_token] = (byte)(length << ML_BITS);
+ }
+
+ // Copy Literals
+ if (length > 0)
+ {
+ _i = dst_p + length;
+ WildCopy(src, src_anchor, dst, dst_p, _i);
+ dst_p = _i;
+ }
+
+ _next_match:
+ // Encode Offset
+ Poke2(dst, dst_p, (ushort)(src_p - src_ref));
+ dst_p += 2;
+
+ // Start Counting
+ src_p += MINMATCH;
+ src_ref += MINMATCH; // MinMatch verified
+ src_anchor = src_p;
+
+ while (src_p < src_LASTLITERALS_STEPSIZE_1)
+ {
+ var diff = (int)Xor4(src, src_ref, src_p);
+ if (diff == 0)
+ {
+ src_p += STEPSIZE_32;
+ src_ref += STEPSIZE_32;
+ continue;
+ }
+ src_p += debruijn32[((uint)((diff) & -(diff)) * 0x077CB531u) >> 27];
+ goto _endCount;
+ }
+
+ if ((src_p < src_LASTLITERALS_1) && (Equal2(src, src_ref, src_p)))
+ {
+ src_p += 2;
+ src_ref += 2;
+ }
+ if ((src_p < src_LASTLITERALS) && (src[src_ref] == src[src_p])) src_p++;
+
+ _endCount:
+
+ // Encode MatchLength
+ len = (src_p - src_anchor);
+
+ if (dst_p + (len >> 8) > dst_LASTLITERALS_1) return 0; // Check output limit
+
+ if (len >= ML_MASK)
+ {
+ dst[dst_token] += ML_MASK;
+ len -= ML_MASK;
+ for (; len > 509; len -= 510)
+ {
+ dst[dst_p++] = 255;
+ dst[dst_p++] = 255;
+ }
+ if (len > 254)
+ {
+ len -= 255;
+ dst[dst_p++] = 255;
+ }
+ dst[dst_p++] = (byte)len;
+ }
+ else
+ {
+ dst[dst_token] += (byte)len;
+ }
+
+ // Test end of chunk
+ if (src_p > src_mflimit)
+ {
+ src_anchor = src_p;
+ break;
+ }
+
+ // Fill table
+ hash_table[(((Peek4(src, src_p - 2)) * 2654435761u) >> HASH64K_ADJUST)] = (ushort)(src_p - 2 - src_base);
+
+ // Test next position
+
+ h = (((Peek4(src, src_p)) * 2654435761u) >> HASH64K_ADJUST);
+ src_ref = src_base + hash_table[h];
+ hash_table[h] = (ushort)(src_p - src_base);
+
+ if (Equal4(src, src_ref, src_p))
+ {
+ dst_token = dst_p++;
+ dst[dst_token] = 0;
+ goto _next_match;
+ }
+
+ // Prepare next loop
+ src_anchor = src_p++;
+ h_fwd = (((Peek4(src, src_p)) * 2654435761u) >> HASH64K_ADJUST);
+ }
+
+ _last_literals:
+ // Encode Last Literals
+ var lastRun = (src_end - src_anchor);
+ if (dst_p + lastRun + 1 + (lastRun - RUN_MASK + 255) / 255 > dst_end) return 0;
+ if (lastRun >= RUN_MASK)
+ {
+ dst[dst_p++] = (RUN_MASK << ML_BITS);
+ lastRun -= RUN_MASK;
+ for (; lastRun > 254; lastRun -= 255) dst[dst_p++] = 255;
+ dst[dst_p++] = (byte)lastRun;
+ }
+ else
+ {
+ dst[dst_p++] = (byte)(lastRun << ML_BITS);
+ }
+ BlockCopy(src, src_anchor, dst, dst_p, src_end - src_anchor);
+ dst_p += src_end - src_anchor;
+
+ // End
+ return ((dst_p) - dst_0);
+ }
+
+ #endregion
+
+ #region LZ4_uncompress
+
+ private static int LZ4_uncompress_safe32(
+ byte[] src,
+ byte[] dst,
+ int src_0,
+ int dst_0,
+ int dst_len)
+ {
+ var dec32table = DECODER_TABLE_32;
+ int _i;
+
+ // ---- preprocessed source start here ----
+ // r93
+ var src_p = src_0;
+ int dst_ref;
+
+ var dst_p = dst_0;
+ var dst_end = dst_p + dst_len;
+ int dst_cpy;
+
+ var dst_LASTLITERALS = dst_end - LASTLITERALS;
+ var dst_COPYLENGTH = dst_end - COPYLENGTH;
+ var dst_COPYLENGTH_STEPSIZE_4 = dst_end - COPYLENGTH - (STEPSIZE_32 - 4);
+
+ byte token;
+
+ // Main Loop
+ while (true)
+ {
+ int length;
+
+ // get runlength
+ token = src[src_p++];
+ if ((length = (token >> ML_BITS)) == RUN_MASK)
+ {
+ int len;
+ for (; (len = src[src_p++]) == 255; length += 255)
+ {
+ /* do nothing */
+ }
+ length += len;
+ }
+
+ // copy literals
+ dst_cpy = dst_p + length;
+
+ if (dst_cpy > dst_COPYLENGTH)
+ {
+ if (dst_cpy != dst_end) goto _output_error; // Error : not enough place for another match (min 4) + 5 literals
+ BlockCopy(src, src_p, dst, dst_p, length);
+ src_p += length;
+ break; // EOF
+ }
+ if (dst_p < dst_cpy)
+ {
+ _i = WildCopy(src, src_p, dst, dst_p, dst_cpy);
+ src_p += _i;
+ dst_p += _i;
+ }
+ src_p -= (dst_p - dst_cpy);
+ dst_p = dst_cpy;
+
+ // get offset
+ dst_ref = (dst_cpy) - Peek2(src, src_p);
+ src_p += 2;
+ if (dst_ref < dst_0) goto _output_error; // Error : offset outside destination buffer
+
+ // get matchlength
+ if ((length = (token & ML_MASK)) == ML_MASK)
+ {
+ for (; src[src_p] == 255; length += 255) src_p++;
+ length += src[src_p++];
+ }
+
+ // copy repeated sequence
+ if ((dst_p - dst_ref) < STEPSIZE_32)
+ {
+ const int dec64 = 0;
+ dst[dst_p + 0] = dst[dst_ref + 0];
+ dst[dst_p + 1] = dst[dst_ref + 1];
+ dst[dst_p + 2] = dst[dst_ref + 2];
+ dst[dst_p + 3] = dst[dst_ref + 3];
+ dst_p += 4;
+ dst_ref += 4;
+ dst_ref -= dec32table[dst_p - dst_ref];
+ Copy4(dst, dst_ref, dst_p);
+ dst_p += STEPSIZE_32 - 4;
+ dst_ref -= dec64;
+ }
+ else
+ {
+ Copy4(dst, dst_ref, dst_p);
+ dst_p += 4;
+ dst_ref += 4;
+ }
+ dst_cpy = dst_p + length - (STEPSIZE_32 - 4);
+
+ if (dst_cpy > dst_COPYLENGTH_STEPSIZE_4)
+ {
+ if (dst_cpy > dst_LASTLITERALS) goto _output_error; // Error : last 5 bytes must be literals
+ if (dst_p < dst_COPYLENGTH)
+ {
+ _i = SecureCopy(dst, dst_ref, dst_p, dst_COPYLENGTH);
+ dst_ref += _i;
+ dst_p += _i;
+ }
+
+ while (dst_p < dst_cpy) dst[dst_p++] = dst[dst_ref++];
+ dst_p = dst_cpy;
+ continue;
+ }
+
+ if (dst_p < dst_cpy)
+ {
+ SecureCopy(dst, dst_ref, dst_p, dst_cpy);
+ }
+ dst_p = dst_cpy; // correction
+ }
+
+ // end of decoding
+ return ((src_p) - src_0);
+
+ // write overflow error detected
+ _output_error:
+ return (-((src_p) - src_0));
+ }
+
+ #endregion
+
+ #region LZ4_uncompress_unknownOutputSize
+
+ private static int LZ4_uncompress_unknownOutputSize_safe32(
+ byte[] src,
+ byte[] dst,
+ int src_0,
+ int dst_0,
+ int src_len,
+ int dst_maxlen)
+ {
+ var dec32table = DECODER_TABLE_32;
+ int _i;
+
+ // ---- preprocessed source start here ----
+ // r93
+ var src_p = src_0;
+ var src_end = src_p + src_len;
+ int dst_ref;
+
+ var dst_p = dst_0;
+ var dst_end = dst_p + dst_maxlen;
+ int dst_cpy;
+
+ var src_LASTLITERALS_3 = (src_end - (2 + 1 + LASTLITERALS));
+ var src_LASTLITERALS_1 = (src_end - (LASTLITERALS + 1));
+ var dst_COPYLENGTH = (dst_end - COPYLENGTH);
+ var dst_COPYLENGTH_STEPSIZE_4 = (dst_end - (COPYLENGTH + (STEPSIZE_32 - 4)));
+ var dst_LASTLITERALS = (dst_end - LASTLITERALS);
+ var dst_MFLIMIT = (dst_end - MFLIMIT);
+
+ // Special case
+ if (src_p == src_end) goto _output_error; // A correctly formed null-compressed LZ4 must have at least one byte (token=0)
+
+ // Main Loop
+ while (true)
+ {
+ byte token;
+ int length;
+
+ // get runlength
+ token = src[src_p++];
+ if ((length = (token >> ML_BITS)) == RUN_MASK)
+ {
+ var s = 255;
+ while ((src_p < src_end) && (s == 255)) length += (s = src[src_p++]);
+ }
+
+ // copy literals
+ dst_cpy = dst_p + length;
+
+ if ((dst_cpy > dst_MFLIMIT) || (src_p + length > src_LASTLITERALS_3))
+ {
+ if (dst_cpy > dst_end) goto _output_error; // Error : writes beyond output buffer
+ if (src_p + length != src_end) goto _output_error; // Error : LZ4 format requires to consume all input at this stage (no match within the last 11 bytes, and at least 8 remaining input bytes for another match+literals)
+ BlockCopy(src, src_p, dst, dst_p, length);
+ dst_p += length;
+ break; // Necessarily EOF, due to parsing restrictions
+ }
+ if (dst_p < dst_cpy)
+ {
+ _i = WildCopy(src, src_p, dst, dst_p, dst_cpy);
+ src_p += _i;
+ dst_p += _i;
+ }
+ src_p -= (dst_p - dst_cpy);
+ dst_p = dst_cpy;
+
+ // get offset
+ dst_ref = (dst_cpy) - Peek2(src, src_p);
+ src_p += 2;
+ if (dst_ref < dst_0) goto _output_error; // Error : offset outside of destination buffer
+
+ // get matchlength
+ if ((length = (token & ML_MASK)) == ML_MASK)
+ {
+ while (src_p < src_LASTLITERALS_1) // Error : a minimum input bytes must remain for LASTLITERALS + token
+ {
+ int s = src[src_p++];
+ length += s;
+ if (s == 255) continue;
+ break;
+ }
+ }
+
+ // copy repeated sequence
+ if (dst_p - dst_ref < STEPSIZE_32)
+ {
+ const int dec64 = 0;
+ dst[dst_p + 0] = dst[dst_ref + 0];
+ dst[dst_p + 1] = dst[dst_ref + 1];
+ dst[dst_p + 2] = dst[dst_ref + 2];
+ dst[dst_p + 3] = dst[dst_ref + 3];
+ dst_p += 4;
+ dst_ref += 4;
+ dst_ref -= dec32table[dst_p - dst_ref];
+ Copy4(dst, dst_ref, dst_p);
+ dst_p += STEPSIZE_32 - 4;
+ dst_ref -= dec64;
+ }
+ else
+ {
+ Copy4(dst, dst_ref, dst_p);
+ dst_p += 4;
+ dst_ref += 4;
+ }
+ dst_cpy = dst_p + length - (STEPSIZE_32 - 4);
+
+ if (dst_cpy > dst_COPYLENGTH_STEPSIZE_4)
+ {
+ if (dst_cpy > dst_LASTLITERALS) goto _output_error; // Error : last 5 bytes must be literals
+ if (dst_p < dst_COPYLENGTH)
+ {
+ _i = SecureCopy(dst, dst_ref, dst_p, dst_COPYLENGTH);
+ dst_ref += _i;
+ dst_p += _i;
+ }
+
+ while (dst_p < dst_cpy) dst[dst_p++] = dst[dst_ref++];
+ dst_p = dst_cpy;
+ continue;
+ }
+
+ if (dst_p < dst_cpy)
+ {
+ SecureCopy(dst, dst_ref, dst_p, dst_cpy);
+ }
+ dst_p = dst_cpy; // correction
+ }
+
+ // end of decoding
+ return ((dst_p) - dst_0);
+
+ // write overflow error detected
+ _output_error:
+ return (-((src_p) - src_0));
+ }
+
+ #endregion
+ }
+}
+
+// ReSharper restore RedundantIfElseBlock
+// ReSharper restore JoinDeclarationAndInitializer
+// ReSharper restore TooWideLocalVariableScope
+// ReSharper restore InconsistentNaming
+// ReSharper restore CheckNamespace
diff --git a/Assets/Scripts/LZ4/LZ4Codec.Safe32.Dirty.cs.meta b/Assets/Scripts/LZ4/LZ4Codec.Safe32.Dirty.cs.meta
new file mode 100644
index 0000000..7086673
--- /dev/null
+++ b/Assets/Scripts/LZ4/LZ4Codec.Safe32.Dirty.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8c5dc5c9f2a382b4db836cf150c3a176
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/LZ4/LZ4Codec.Safe32HC.Dirty.cs b/Assets/Scripts/LZ4/LZ4Codec.Safe32HC.Dirty.cs
new file mode 100644
index 0000000..446bbfd
--- /dev/null
+++ b/Assets/Scripts/LZ4/LZ4Codec.Safe32HC.Dirty.cs
@@ -0,0 +1,524 @@
+#region LZ4 original
+
+/*
+ LZ4 - Fast LZ compression algorithm
+ Copyright (C) 2011-2012, Yann Collet.
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ You can contact the author at :
+ - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
+ - LZ4 source repository : http://code.google.com/p/lz4/
+*/
+
+#endregion
+
+#region LZ4 port
+
+/*
+Copyright (c) 2013, Milosz Krajewski
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided
+that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this list of conditions
+ and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
+ and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#endregion
+
+// ReSharper disable InconsistentNaming
+
+namespace LZ4ps
+{
+ public static partial class LZ4Codec
+ {
+ // Update chains up to ip (excluded)
+ private static void LZ4HC_Insert_32(LZ4HC_Data_Structure ctx, int src_p)
+ {
+ var chainTable = ctx.chainTable;
+ var hashTable = ctx.hashTable;
+ var nextToUpdate = ctx.nextToUpdate;
+ var src = ctx.src;
+ var src_base = ctx.src_base;
+
+ while (nextToUpdate < src_p)
+ {
+ var p = nextToUpdate;
+ var delta = (p) - (hashTable[(((Peek4(src, p)) * 2654435761u) >> HASHHC_ADJUST)] + src_base);
+ if (delta > MAX_DISTANCE) delta = MAX_DISTANCE;
+ chainTable[(p) & MAXD_MASK] = (ushort)delta;
+ hashTable[(((Peek4(src, p)) * 2654435761u) >> HASHHC_ADJUST)] = ((p) - src_base);
+ nextToUpdate++;
+ }
+
+ ctx.nextToUpdate = nextToUpdate;
+ }
+
+ private static int LZ4HC_CommonLength_32(LZ4HC_Data_Structure ctx, int p1, int p2)
+ {
+ var debruijn32 = DEBRUIJN_TABLE_32;
+ var src = ctx.src;
+ var src_LASTLITERALS = ctx.src_LASTLITERALS;
+
+ var p1t = p1;
+
+ while (p1t < src_LASTLITERALS - (STEPSIZE_32 - 1))
+ {
+ var diff = (int)Xor4(src, p2, p1t);
+ if (diff == 0)
+ {
+ p1t += STEPSIZE_32;
+ p2 += STEPSIZE_32;
+ continue;
+ }
+ p1t += debruijn32[((uint)((diff) & -(diff)) * 0x077CB531u) >> 27];
+ return (p1t - p1);
+ }
+ if ((p1t < (src_LASTLITERALS - 1)) && (Equal2(src, p2, p1t)))
+ {
+ p1t += 2;
+ p2 += 2;
+ }
+ if ((p1t < src_LASTLITERALS) && (src[p2] == src[p1t])) p1t++;
+ return (p1t - p1);
+ }
+
+ private static int LZ4HC_InsertAndFindBestMatch_32(LZ4HC_Data_Structure ctx, int src_p, ref int src_match)
+ {
+ var chainTable = ctx.chainTable;
+ var hashTable = ctx.hashTable;
+ var src = ctx.src;
+ var src_base = ctx.src_base;
+
+ var nbAttempts = MAX_NB_ATTEMPTS;
+ int repl = 0, ml = 0;
+ ushort delta = 0;
+
+ // HC4 match finder
+ LZ4HC_Insert_32(ctx, src_p);
+ var src_ref = (hashTable[(((Peek4(src, src_p)) * 2654435761u) >> HASHHC_ADJUST)] + src_base);
+
+
+ // Detect repetitive sequences of length <= 4
+ if (src_ref >= src_p - 4) // potential repetition
+ {
+ if (Equal4(src, src_ref, src_p)) // confirmed
+ {
+ delta = (ushort)(src_p - src_ref);
+ repl = ml = LZ4HC_CommonLength_32(ctx, src_p + MINMATCH, src_ref + MINMATCH) + MINMATCH;
+ src_match = src_ref;
+ }
+ src_ref = ((src_ref) - chainTable[(src_ref) & MAXD_MASK]);
+ }
+
+ while ((src_ref >= src_p - MAX_DISTANCE) && (nbAttempts != 0))
+ {
+ nbAttempts--;
+ if (src[(src_ref + ml)] == src[(src_p + ml)])
+ {
+ if (Equal4(src, src_ref, src_p))
+ {
+ var mlt = LZ4HC_CommonLength_32(ctx, src_p + MINMATCH, src_ref + MINMATCH) + MINMATCH;
+ if (mlt > ml)
+ {
+ ml = mlt;
+ src_match = src_ref;
+ }
+ }
+ }
+ src_ref = ((src_ref) - chainTable[(src_ref) & MAXD_MASK]);
+ }
+
+
+ // Complete table
+ if (repl != 0)
+ {
+ var src_ptr = src_p;
+
+ var end = src_p + repl - (MINMATCH - 1);
+ while (src_ptr < end - delta)
+ {
+ chainTable[(src_ptr) & MAXD_MASK] = delta; // Pre-Load
+ src_ptr++;
+ }
+ do
+ {
+ chainTable[(src_ptr) & MAXD_MASK] = delta;
+ hashTable[(((Peek4(src, src_ptr)) * 2654435761u) >> HASHHC_ADJUST)] = ((src_ptr) - src_base); // Head of chain
+ src_ptr++;
+ } while (src_ptr < end);
+ ctx.nextToUpdate = end;
+ }
+
+ return ml;
+ }
+
+ private static int LZ4HC_InsertAndGetWiderMatch_32(
+ LZ4HC_Data_Structure ctx, int src_p, int startLimit, int longest, ref int matchpos, ref int startpos)
+ {
+ var chainTable = ctx.chainTable;
+ var hashTable = ctx.hashTable;
+ var src = ctx.src;
+ var src_base = ctx.src_base;
+ var src_LASTLITERALS = ctx.src_LASTLITERALS;
+ var debruijn32 = DEBRUIJN_TABLE_32;
+ var nbAttempts = MAX_NB_ATTEMPTS;
+ var delta = (src_p - startLimit);
+
+ // First Match
+ LZ4HC_Insert_32(ctx, src_p);
+ var src_ref = (hashTable[(((Peek4(src, src_p)) * 2654435761u) >> HASHHC_ADJUST)] + src_base);
+
+ while ((src_ref >= src_p - MAX_DISTANCE) && (nbAttempts != 0))
+ {
+ nbAttempts--;
+ if (src[(startLimit + longest)] == src[(src_ref - delta + longest)])
+ {
+ if (Equal4(src, src_ref, src_p))
+ {
+ var reft = src_ref + MINMATCH;
+ var ipt = src_p + MINMATCH;
+ var startt = src_p;
+
+ while (ipt < src_LASTLITERALS - (STEPSIZE_32 - 1))
+ {
+ var diff = (int)Xor4(src, reft, ipt);
+ if (diff == 0)
+ {
+ ipt += STEPSIZE_32;
+ reft += STEPSIZE_32;
+ continue;
+ }
+ ipt += debruijn32[((uint)((diff) & -(diff)) * 0x077CB531u) >> 27];
+ goto _endCount;
+ }
+ if ((ipt < (src_LASTLITERALS - 1)) && (Equal2(src, reft, ipt)))
+ {
+ ipt += 2;
+ reft += 2;
+ }
+ if ((ipt < src_LASTLITERALS) && (src[reft] == src[ipt])) ipt++;
+
+ _endCount:
+ reft = src_ref;
+
+ while ((startt > startLimit) && (reft > src_base) && (src[startt - 1] == src[reft - 1]))
+ {
+ startt--;
+ reft--;
+ }
+
+ if ((ipt - startt) > longest)
+ {
+ longest = (ipt - startt);
+ matchpos = reft;
+ startpos = startt;
+ }
+ }
+ }
+ src_ref = ((src_ref) - chainTable[(src_ref) & MAXD_MASK]);
+ }
+
+ return longest;
+ }
+
+ private static int LZ4_encodeSequence_32(
+ LZ4HC_Data_Structure ctx, ref int src_p, ref int dst_p, ref int src_anchor, int matchLength, int src_ref, int dst_end)
+ {
+ int len;
+ var src = ctx.src;
+ var dst = ctx.dst;
+
+ // Encode Literal length
+ var length = src_p - src_anchor;
+ var dst_token = dst_p++;
+ if ((dst_p + length + (2 + 1 + LASTLITERALS) + (length >> 8)) > dst_end) return 1; // Check output limit
+ if (length >= RUN_MASK)
+ {
+ dst[dst_token] = (RUN_MASK << ML_BITS);
+ len = length - RUN_MASK;
+ for (; len > 254; len -= 255) dst[dst_p++] = 255;
+ dst[dst_p++] = (byte)len;
+ }
+ else
+ {
+ dst[dst_token] = (byte)(length << ML_BITS);
+ }
+
+ // Copy Literals
+ if (length > 0)
+ {
+ var _i = dst_p + length;
+ src_anchor += WildCopy(src, src_anchor, dst, dst_p, _i);
+ dst_p = _i;
+ }
+
+ // Encode Offset
+ Poke2(dst, dst_p, (ushort)(src_p - src_ref));
+ dst_p += 2;
+
+ // Encode MatchLength
+ len = (matchLength - MINMATCH);
+ if (dst_p + (1 + LASTLITERALS) + (length >> 8) > dst_end) return 1; // Check output limit
+ if (len >= ML_MASK)
+ {
+ dst[dst_token] += ML_MASK;
+ len -= ML_MASK;
+ for (; len > 509; len -= 510)
+ {
+ dst[(dst_p)++] = 255;
+ dst[(dst_p)++] = 255;
+ }
+ if (len > 254)
+ {
+ len -= 255;
+ dst[(dst_p)++] = 255;
+ }
+ dst[(dst_p)++] = (byte)len;
+ }
+ else
+ {
+ dst[dst_token] += (byte)len;
+ }
+
+ // Prepare next loop
+ src_p += matchLength;
+ src_anchor = src_p;
+
+ return 0;
+ }
+
+ private static int LZ4_compressHCCtx_32(LZ4HC_Data_Structure ctx)
+ {
+ var src = ctx.src;
+ var dst = ctx.dst;
+ var src_0 = ctx.src_base;
+ var src_end = ctx.src_end;
+ var dst_0 = ctx.dst_base;
+ var dst_len = ctx.dst_len;
+ var dst_end = ctx.dst_end;
+
+ var src_p = src_0;
+ var src_anchor = src_p;
+ var src_mflimit = src_end - MFLIMIT;
+
+ var dst_p = dst_0;
+
+ var src_ref = 0;
+ var start2 = 0;
+ var ref2 = 0;
+ var start3 = 0;
+ var ref3 = 0;
+
+ src_p++;
+
+ // Main Loop
+ while (src_p < src_mflimit)
+ {
+ var ml = LZ4HC_InsertAndFindBestMatch_32(ctx, src_p, ref src_ref);
+ if (ml == 0)
+ {
+ src_p++;
+ continue;
+ }
+
+ // saved, in case we would skip too much
+ var start0 = src_p;
+ var ref0 = src_ref;
+ var ml0 = ml;
+
+ _Search2:
+ var ml2 = src_p + ml < src_mflimit
+ ? LZ4HC_InsertAndGetWiderMatch_32(ctx, src_p + ml - 2, src_p + 1, ml, ref ref2, ref start2)
+ : ml;
+
+ if (ml2 == ml) // No better match
+ {
+ if (LZ4_encodeSequence_32(ctx, ref src_p, ref dst_p, ref src_anchor, ml, src_ref, dst_end) != 0) return 0;
+ continue;
+ }
+
+ if (start0 < src_p)
+ {
+ if (start2 < src_p + ml0) // empirical
+ {
+ src_p = start0;
+ src_ref = ref0;
+ ml = ml0;
+ }
+ }
+
+ // Here, start0==ip
+ if ((start2 - src_p) < 3) // First Match too small : removed
+ {
+ ml = ml2;
+ src_p = start2;
+ src_ref = ref2;
+ goto _Search2;
+ }
+
+ _Search3:
+ // Currently we have :
+ // ml2 > ml1, and
+ // ip1+3 <= ip2 (usually < ip1+ml1)
+ if ((start2 - src_p) < OPTIMAL_ML)
+ {
+ var new_ml = ml;
+ if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML;
+ if (src_p + new_ml > start2 + ml2 - MINMATCH) new_ml = (start2 - src_p) + ml2 - MINMATCH;
+ var correction = new_ml - (start2 - src_p);
+ if (correction > 0)
+ {
+ start2 += correction;
+ ref2 += correction;
+ ml2 -= correction;
+ }
+ }
+ // Now, we have start2 = ip+new_ml, with new_ml=min(ml, OPTIMAL_ML=18)
+
+ var ml3 = start2 + ml2 < src_mflimit
+ ? LZ4HC_InsertAndGetWiderMatch_32(ctx, start2 + ml2 - 3, start2, ml2, ref ref3, ref start3)
+ : ml2;
+
+ if (ml3 == ml2) // No better match : 2 sequences to encode
+ {
+ // ip & ref are known; Now for ml
+ if (start2 < src_p + ml) ml = (start2 - src_p);
+ // Now, encode 2 sequences
+ if (LZ4_encodeSequence_32(ctx, ref src_p, ref dst_p, ref src_anchor, ml, src_ref, dst_end) != 0) return 0;
+ src_p = start2;
+ if (LZ4_encodeSequence_32(ctx, ref src_p, ref dst_p, ref src_anchor, ml2, ref2, dst_end) != 0) return 0;
+ continue;
+ }
+
+ if (start3 < src_p + ml + 3) // Not enough space for match 2 : remove it
+ {
+ if (start3 >= (src_p + ml)) // can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1
+ {
+ if (start2 < src_p + ml)
+ {
+ var correction = (src_p + ml - start2);
+ start2 += correction;
+ ref2 += correction;
+ ml2 -= correction;
+ if (ml2 < MINMATCH)
+ {
+ start2 = start3;
+ ref2 = ref3;
+ ml2 = ml3;
+ }
+ }
+
+ if (LZ4_encodeSequence_32(ctx, ref src_p, ref dst_p, ref src_anchor, ml, src_ref, dst_end) != 0) return 0;
+ src_p = start3;
+ src_ref = ref3;
+ ml = ml3;
+
+ start0 = start2;
+ ref0 = ref2;
+ ml0 = ml2;
+ goto _Search2;
+ }
+
+ start2 = start3;
+ ref2 = ref3;
+ ml2 = ml3;
+ goto _Search3;
+ }
+
+ // OK, now we have 3 ascending matches; let's write at least the first one
+ // ip & ref are known; Now for ml
+ if (start2 < src_p + ml)
+ {
+ if ((start2 - src_p) < ML_MASK)
+ {
+ if (ml > OPTIMAL_ML) ml = OPTIMAL_ML;
+ if (src_p + ml > start2 + ml2 - MINMATCH) ml = (start2 - src_p) + ml2 - MINMATCH;
+ var correction = ml - (start2 - src_p);
+ if (correction > 0)
+ {
+ start2 += correction;
+ ref2 += correction;
+ ml2 -= correction;
+ }
+ }
+ else
+ {
+ ml = (start2 - src_p);
+ }
+ }
+ if (LZ4_encodeSequence_32(ctx, ref src_p, ref dst_p, ref src_anchor, ml, src_ref, dst_end) != 0) return 0;
+
+ src_p = start2;
+ src_ref = ref2;
+ ml = ml2;
+
+ start2 = start3;
+ ref2 = ref3;
+ ml2 = ml3;
+
+ goto _Search3;
+ }
+
+ // Encode Last Literals
+ {
+ var lastRun = (src_end - src_anchor);
+ if ((dst_p - dst_0) + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > (uint)dst_len) return 0; // Check output limit
+ if (lastRun >= RUN_MASK)
+ {
+ dst[dst_p++] = (RUN_MASK << ML_BITS);
+ lastRun -= RUN_MASK;
+ for (; lastRun > 254; lastRun -= 255) dst[dst_p++] = 255;
+ dst[dst_p++] = (byte)lastRun;
+ }
+ else
+ {
+ dst[dst_p++] = (byte)(lastRun << ML_BITS);
+ }
+ BlockCopy(src, src_anchor, dst, dst_p, src_end - src_anchor);
+ dst_p += src_end - src_anchor;
+ }
+
+ // End
+ return (dst_p - dst_0);
+ }
+ }
+}
+
+// ReSharper restore InconsistentNaming
diff --git a/Assets/Scripts/LZ4/LZ4Codec.Safe32HC.Dirty.cs.meta b/Assets/Scripts/LZ4/LZ4Codec.Safe32HC.Dirty.cs.meta
new file mode 100644
index 0000000..f1a35b3
--- /dev/null
+++ b/Assets/Scripts/LZ4/LZ4Codec.Safe32HC.Dirty.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0cd0b555f5386b84b9fc6aea0b43418d
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/LZ4/LZ4Codec.Safe64.Dirty.cs b/Assets/Scripts/LZ4/LZ4Codec.Safe64.Dirty.cs
new file mode 100644
index 0000000..fbeee17
--- /dev/null
+++ b/Assets/Scripts/LZ4/LZ4Codec.Safe64.Dirty.cs
@@ -0,0 +1,808 @@
+#region LZ4 original
+
+/*
+ LZ4 - Fast LZ compression algorithm
+ Copyright (C) 2011-2012, Yann Collet.
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ You can contact the author at :
+ - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
+ - LZ4 source repository : http://code.google.com/p/lz4/
+*/
+
+#endregion
+
+#region LZ4 port
+
+/*
+Copyright (c) 2013, Milosz Krajewski
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided
+that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this list of conditions
+ and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
+ and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#endregion
+
+// ReSharper disable CheckNamespace
+// ReSharper disable InconsistentNaming
+// ReSharper disable TooWideLocalVariableScope
+// ReSharper disable JoinDeclarationAndInitializer
+// ReSharper disable RedundantIfElseBlock
+
+namespace LZ4ps
+{
+ public static partial class LZ4Codec
+ {
+ #region LZ4_compressCtx
+
+ private static int LZ4_compressCtx_safe64(
+ int[] hash_table,
+ byte[] src,
+ byte[] dst,
+ int src_0,
+ int dst_0,
+ int src_len,
+ int dst_maxlen)
+ {
+ var debruijn64 = DEBRUIJN_TABLE_64;
+ int _i;
+
+ // ---- preprocessed source start here ----
+ // r93
+ var src_p = src_0;
+ var src_base = src_0;
+ var src_anchor = src_p;
+ var src_end = src_p + src_len;
+ var src_mflimit = src_end - MFLIMIT;
+
+ var dst_p = dst_0;
+ var dst_end = dst_p + dst_maxlen;
+
+ var src_LASTLITERALS = src_end - LASTLITERALS;
+ var src_LASTLITERALS_1 = src_LASTLITERALS - 1;
+
+ var src_LASTLITERALS_3 = src_LASTLITERALS - 3;
+
+ var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_64 - 1);
+ var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS);
+ var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS);
+
+ int length;
+
+ uint h, h_fwd;
+
+ // Init
+ if (src_len < MINLENGTH) goto _last_literals;
+
+ // First Byte
+ hash_table[(((Peek4(src, src_p)) * 2654435761u) >> HASH_ADJUST)] = (src_p - src_base);
+ src_p++;
+ h_fwd = (((Peek4(src, src_p)) * 2654435761u) >> HASH_ADJUST);
+
+ // Main Loop
+ while (true)
+ {
+ var findMatchAttempts = (1 << SKIPSTRENGTH) + 3;
+ var src_p_fwd = src_p;
+ int src_ref;
+ int dst_token;
+
+ // Find a match
+ do
+ {
+ h = h_fwd;
+ var step = findMatchAttempts++ >> SKIPSTRENGTH;
+ src_p = src_p_fwd;
+ src_p_fwd = src_p + step;
+
+ if (src_p_fwd > src_mflimit) goto _last_literals;
+
+ h_fwd = (((Peek4(src, src_p_fwd)) * 2654435761u) >> HASH_ADJUST);
+ src_ref = src_base + hash_table[h];
+ hash_table[h] = (src_p - src_base);
+ } while ((src_ref < src_p - MAX_DISTANCE) || (!Equal4(src, src_ref, src_p)));
+
+ // Catch up
+ while ((src_p > src_anchor) && (src_ref > src_0) && (src[src_p - 1] == src[src_ref - 1]))
+ {
+ src_p--;
+ src_ref--;
+ }
+
+ // Encode Literal length
+ length = (src_p - src_anchor);
+ dst_token = dst_p++;
+
+ if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3) return 0; // Check output limit
+
+ if (length >= RUN_MASK)
+ {
+ var len = length - RUN_MASK;
+ dst[dst_token] = (RUN_MASK << ML_BITS);
+ if (len > 254)
+ {
+ do
+ {
+ dst[dst_p++] = 255;
+ len -= 255;
+ } while (len > 254);
+ dst[dst_p++] = (byte)len;
+ BlockCopy(src, src_anchor, dst, dst_p, length);
+ dst_p += length;
+ goto _next_match;
+ }
+ else
+ dst[dst_p++] = (byte)len;
+ }
+ else
+ {
+ dst[dst_token] = (byte)(length << ML_BITS);
+ }
+
+ // Copy Literals
+ if (length > 0)
+ {
+ _i = dst_p + length;
+ WildCopy(src, src_anchor, dst, dst_p, _i);
+ dst_p = _i;
+ }
+
+ _next_match:
+ // Encode Offset
+ Poke2(dst, dst_p, (ushort)(src_p - src_ref));
+ dst_p += 2;
+
+ // Start Counting
+ src_p += MINMATCH;
+ src_ref += MINMATCH; // MinMatch already verified
+ src_anchor = src_p;
+
+ while (src_p < src_LASTLITERALS_STEPSIZE_1)
+ {
+ var diff = (long)Xor8(src, src_ref, src_p);
+ if (diff == 0)
+ {
+ src_p += STEPSIZE_64;
+ src_ref += STEPSIZE_64;
+ continue;
+ }
+ src_p += debruijn64[((ulong)((diff) & -(diff)) * 0x0218A392CDABBD3FL) >> 58];
+ goto _endCount;
+ }
+
+ if ((src_p < src_LASTLITERALS_3) && (Equal4(src, src_ref, src_p)))
+ {
+ src_p += 4;
+ src_ref += 4;
+ }
+ if ((src_p < src_LASTLITERALS_1) && (Equal2(src, src_ref, src_p)))
+ {
+ src_p += 2;
+ src_ref += 2;
+ }
+ if ((src_p < src_LASTLITERALS) && (src[src_ref] == src[src_p])) src_p++;
+
+ _endCount:
+ // Encode MatchLength
+ length = (src_p - src_anchor);
+
+ if (dst_p + (length >> 8) > dst_LASTLITERALS_1) return 0; // Check output limit
+
+ if (length >= ML_MASK)
+ {
+ dst[dst_token] += ML_MASK;
+ length -= ML_MASK;
+ for (; length > 509; length -= 510)
+ {
+ dst[dst_p++] = 255;
+ dst[dst_p++] = 255;
+ }
+ if (length > 254)
+ {
+ length -= 255;
+ dst[dst_p++] = 255;
+ }
+ dst[dst_p++] = (byte)length;
+ }
+ else
+ {
+ dst[dst_token] += (byte)length;
+ }
+
+ // Test end of chunk
+ if (src_p > src_mflimit)
+ {
+ src_anchor = src_p;
+ break;
+ }
+
+ // Fill table
+ hash_table[(((Peek4(src, src_p - 2)) * 2654435761u) >> HASH_ADJUST)] = (src_p - 2 - src_base);
+
+ // Test next position
+
+ h = (((Peek4(src, src_p)) * 2654435761u) >> HASH_ADJUST);
+ src_ref = src_base + hash_table[h];
+ hash_table[h] = (src_p - src_base);
+
+ if ((src_ref > src_p - (MAX_DISTANCE + 1)) && (Equal4(src, src_ref, src_p)))
+ {
+ dst_token = dst_p++;
+ dst[dst_token] = 0;
+ goto _next_match;
+ }
+
+ // Prepare next loop
+ src_anchor = src_p++;
+ h_fwd = (((Peek4(src, src_p)) * 2654435761u) >> HASH_ADJUST);
+ }
+
+ _last_literals:
+ // Encode Last Literals
+ {
+ var lastRun = (src_end - src_anchor);
+
+ if (dst_p + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > dst_end) return 0;
+
+ if (lastRun >= RUN_MASK)
+ {
+ dst[dst_p++] = (RUN_MASK << ML_BITS);
+ lastRun -= RUN_MASK;
+ for (; lastRun > 254; lastRun -= 255) dst[dst_p++] = 255;
+ dst[dst_p++] = (byte)lastRun;
+ }
+ else dst[dst_p++] = (byte)(lastRun << ML_BITS);
+ BlockCopy(src, src_anchor, dst, dst_p, src_end - src_anchor);
+ dst_p += src_end - src_anchor;
+ }
+
+ // End
+ return (dst_p - dst_0);
+ }
+
+ #endregion
+
+ #region LZ4_compress64kCtx
+
+ private static int LZ4_compress64kCtx_safe64(
+ ushort[] hash_table,
+ byte[] src,
+ byte[] dst,
+ int src_0,
+ int dst_0,
+ int src_len,
+ int dst_maxlen)
+ {
+ var debruijn64 = DEBRUIJN_TABLE_64;
+ int _i;
+
+ // ---- preprocessed source start here ----
+ // r93
+ var src_p = src_0;
+ var src_anchor = src_p;
+ var src_base = src_p;
+ var src_end = src_p + src_len;
+ var src_mflimit = src_end - MFLIMIT;
+
+ var dst_p = dst_0;
+ var dst_end = dst_p + dst_maxlen;
+
+ var src_LASTLITERALS = src_end - LASTLITERALS;
+ var src_LASTLITERALS_1 = src_LASTLITERALS - 1;
+
+ var src_LASTLITERALS_3 = src_LASTLITERALS - 3;
+
+ var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_64 - 1);
+ var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS);
+ var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS);
+
+ int len, length;
+
+ uint h, h_fwd;
+
+ // Init
+ if (src_len < MINLENGTH) goto _last_literals;
+
+ // First Byte
+ src_p++;
+ h_fwd = (((Peek4(src, src_p)) * 2654435761u) >> HASH64K_ADJUST);
+
+ // Main Loop
+ while (true)
+ {
+ var findMatchAttempts = (1 << SKIPSTRENGTH) + 3;
+ var src_p_fwd = src_p;
+ int src_ref;
+ int dst_token;
+
+ // Find a match
+ do
+ {
+ h = h_fwd;
+ var step = findMatchAttempts++ >> SKIPSTRENGTH;
+ src_p = src_p_fwd;
+ src_p_fwd = src_p + step;
+
+ if (src_p_fwd > src_mflimit) goto _last_literals;
+
+ h_fwd = (((Peek4(src, src_p_fwd)) * 2654435761u) >> HASH64K_ADJUST);
+ src_ref = src_base + hash_table[h];
+ hash_table[h] = (ushort)(src_p - src_base);
+ } while (!Equal4(src, src_ref, src_p));
+
+ // Catch up
+ while ((src_p > src_anchor) && (src_ref > src_0) && (src[src_p - 1] == src[src_ref - 1]))
+ {
+ src_p--;
+ src_ref--;
+ }
+
+ // Encode Literal length
+ length = (src_p - src_anchor);
+ dst_token = dst_p++;
+
+ if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3) return 0; // Check output limit
+
+ if (length >= RUN_MASK)
+ {
+ len = length - RUN_MASK;
+ dst[dst_token] = (RUN_MASK << ML_BITS);
+ if (len > 254)
+ {
+ do
+ {
+ dst[dst_p++] = 255;
+ len -= 255;
+ } while (len > 254);
+ dst[dst_p++] = (byte)len;
+ BlockCopy(src, src_anchor, dst, dst_p, length);
+ dst_p += length;
+ goto _next_match;
+ }
+ else
+ dst[dst_p++] = (byte)len;
+ }
+ else
+ {
+ dst[dst_token] = (byte)(length << ML_BITS);
+ }
+
+ // Copy Literals
+ if (length > 0) /*?*/
+ {
+ _i = dst_p + length;
+ WildCopy(src, src_anchor, dst, dst_p, _i);
+ dst_p = _i;
+ }
+
+ _next_match:
+ // Encode Offset
+ Poke2(dst, dst_p, (ushort)(src_p - src_ref));
+ dst_p += 2;
+
+ // Start Counting
+ src_p += MINMATCH;
+ src_ref += MINMATCH; // MinMatch verified
+ src_anchor = src_p;
+
+ while (src_p < src_LASTLITERALS_STEPSIZE_1)
+ {
+ var diff = (long)Xor8(src, src_ref, src_p);
+ if (diff == 0)
+ {
+ src_p += STEPSIZE_64;
+ src_ref += STEPSIZE_64;
+ continue;
+ }
+ src_p += debruijn64[((ulong)((diff) & -(diff)) * 0x0218A392CDABBD3FL) >> 58];
+ goto _endCount;
+ }
+
+ if ((src_p < src_LASTLITERALS_3) && (Equal4(src, src_ref, src_p)))
+ {
+ src_p += 4;
+ src_ref += 4;
+ }
+ if ((src_p < src_LASTLITERALS_1) && (Equal2(src, src_ref, src_p)))
+ {
+ src_p += 2;
+ src_ref += 2;
+ }
+ if ((src_p < src_LASTLITERALS) && (src[src_ref] == src[src_p])) src_p++;
+
+ _endCount:
+
+ // Encode MatchLength
+ len = (src_p - src_anchor);
+
+ if (dst_p + (len >> 8) > dst_LASTLITERALS_1) return 0; // Check output limit
+
+ if (len >= ML_MASK)
+ {
+ dst[dst_token] += ML_MASK;
+ len -= ML_MASK;
+ for (; len > 509; len -= 510)
+ {
+ dst[dst_p++] = 255;
+ dst[dst_p++] = 255;
+ }
+ if (len > 254)
+ {
+ len -= 255;
+ dst[dst_p++] = 255;
+ }
+ dst[dst_p++] = (byte)len;
+ }
+ else
+ {
+ dst[dst_token] += (byte)len;
+ }
+
+ // Test end of chunk
+ if (src_p > src_mflimit)
+ {
+ src_anchor = src_p;
+ break;
+ }
+
+ // Fill table
+ hash_table[(((Peek4(src, src_p - 2)) * 2654435761u) >> HASH64K_ADJUST)] = (ushort)(src_p - 2 - src_base);
+
+ // Test next position
+
+ h = (((Peek4(src, src_p)) * 2654435761u) >> HASH64K_ADJUST);
+ src_ref = src_base + hash_table[h];
+ hash_table[h] = (ushort)(src_p - src_base);
+
+ if (Equal4(src, src_ref, src_p))
+ {
+ dst_token = dst_p++;
+ dst[dst_token] = 0;
+ goto _next_match;
+ }
+
+ // Prepare next loop
+ src_anchor = src_p++;
+ h_fwd = (((Peek4(src, src_p)) * 2654435761u) >> HASH64K_ADJUST);
+ }
+
+ _last_literals:
+ // Encode Last Literals
+ {
+ var lastRun = (src_end - src_anchor);
+ if (dst_p + lastRun + 1 + (lastRun - RUN_MASK + 255) / 255 > dst_end) return 0;
+ if (lastRun >= RUN_MASK)
+ {
+ dst[dst_p++] = (RUN_MASK << ML_BITS);
+ lastRun -= RUN_MASK;
+ for (; lastRun > 254; lastRun -= 255) dst[dst_p++] = 255;
+ dst[dst_p++] = (byte)lastRun;
+ }
+ else dst[dst_p++] = (byte)(lastRun << ML_BITS);
+ BlockCopy(src, src_anchor, dst, dst_p, src_end - src_anchor);
+ dst_p += src_end - src_anchor;
+ }
+
+ // End
+ return (dst_p - dst_0);
+ }
+
+ #endregion
+
+ #region LZ4_uncompress
+
+ private static int LZ4_uncompress_safe64(
+ byte[] src,
+ byte[] dst,
+ int src_0,
+ int dst_0,
+ int dst_len)
+ {
+ var dec32table = DECODER_TABLE_32;
+ var dec64table = DECODER_TABLE_64;
+ int _i;
+
+ // ---- preprocessed source start here ----
+ // r93
+ var src_p = src_0;
+ int dst_ref;
+
+ var dst_p = dst_0;
+ var dst_end = dst_p + dst_len;
+ int dst_cpy;
+
+ var dst_LASTLITERALS = dst_end - LASTLITERALS;
+ var dst_COPYLENGTH = dst_end - COPYLENGTH;
+ var dst_COPYLENGTH_STEPSIZE_4 = dst_end - COPYLENGTH - (STEPSIZE_64 - 4);
+
+ uint token;
+
+ // Main Loop
+ while (true)
+ {
+ int length;
+
+ // get runlength
+ token = src[src_p++];
+ if ((length = (byte)(token >> ML_BITS)) == RUN_MASK)
+ {
+ int len;
+ for (; (len = src[src_p++]) == 255; length += 255)
+ {
+ /* do nothing */
+ }
+ length += len;
+ }
+
+ // copy literals
+ dst_cpy = dst_p + length;
+
+ if (dst_cpy > dst_COPYLENGTH)
+ {
+ if (dst_cpy != dst_end) goto _output_error; // Error : not enough place for another match (min 4) + 5 literals
+ BlockCopy(src, src_p, dst, dst_p, length);
+ src_p += length;
+ break; // EOF
+ }
+ if (dst_p < dst_cpy) /*?*/
+ {
+ _i = WildCopy(src, src_p, dst, dst_p, dst_cpy);
+ src_p += _i;
+ dst_p += _i;
+ }
+ src_p -= (dst_p - dst_cpy);
+ dst_p = dst_cpy;
+
+ // get offset
+ dst_ref = (dst_cpy) - Peek2(src, src_p);
+ src_p += 2;
+ if (dst_ref < dst_0) goto _output_error; // Error : offset outside destination buffer
+
+ // get matchlength
+ if ((length = (byte)(token & ML_MASK)) == ML_MASK)
+ {
+ for (; src[src_p] == 255; length += 255) src_p++;
+ length += src[src_p++];
+ }
+
+ // copy repeated sequence
+ if ((dst_p - dst_ref) < STEPSIZE_64)
+ {
+ var dec64 = dec64table[dst_p - dst_ref];
+
+ dst[dst_p + 0] = dst[dst_ref + 0];
+ dst[dst_p + 1] = dst[dst_ref + 1];
+ dst[dst_p + 2] = dst[dst_ref + 2];
+ dst[dst_p + 3] = dst[dst_ref + 3];
+ dst_p += 4;
+ dst_ref += 4;
+ dst_ref -= dec32table[dst_p - dst_ref];
+ Copy4(dst, dst_ref, dst_p);
+ dst_p += STEPSIZE_64 - 4;
+ dst_ref -= dec64;
+ }
+ else
+ {
+ Copy8(dst, dst_ref, dst_p);
+ dst_p += 8;
+ dst_ref += 8;
+ }
+ dst_cpy = dst_p + length - (STEPSIZE_64 - 4);
+
+ if (dst_cpy > dst_COPYLENGTH_STEPSIZE_4)
+ {
+ if (dst_cpy > dst_LASTLITERALS) goto _output_error; // Error : last 5 bytes must be literals
+ if (dst_p < dst_COPYLENGTH)
+ {
+ _i = SecureCopy(dst, dst_ref, dst_p, dst_COPYLENGTH);
+ dst_ref += _i;
+ dst_p += _i;
+ }
+
+ while (dst_p < dst_cpy) dst[dst_p++] = dst[dst_ref++];
+ dst_p = dst_cpy;
+ continue;
+ }
+
+ if (dst_p < dst_cpy)
+ {
+ SecureCopy(dst, dst_ref, dst_p, dst_cpy);
+ }
+ dst_p = dst_cpy; // correction
+ }
+
+ // end of decoding
+ return ((src_p) - src_0);
+
+ _output_error:
+ // write overflow error detected
+ return (-((src_p) - src_0));
+ }
+
+ #endregion
+
+ #region LZ4_uncompress_unknownOutputSize
+
+ private static int LZ4_uncompress_unknownOutputSize_safe64(
+ byte[] src,
+ byte[] dst,
+ int src_0,
+ int dst_0,
+ int src_len,
+ int dst_maxlen)
+ {
+ var dec32table = DECODER_TABLE_32;
+ var dec64table = DECODER_TABLE_64;
+ int _i;
+
+ // ---- preprocessed source start here ----
+ // r93
+ var src_p = src_0;
+ var src_end = src_p + src_len;
+ int dst_ref;
+
+ var dst_p = dst_0;
+ var dst_end = dst_p + dst_maxlen;
+ int dst_cpy;
+
+ var src_LASTLITERALS_3 = (src_end - (2 + 1 + LASTLITERALS));
+ var src_LASTLITERALS_1 = (src_end - (LASTLITERALS + 1));
+ var dst_COPYLENGTH = (dst_end - COPYLENGTH);
+ var dst_COPYLENGTH_STEPSIZE_4 = (dst_end - (COPYLENGTH + (STEPSIZE_64 - 4)));
+ var dst_LASTLITERALS = (dst_end - LASTLITERALS);
+ var dst_MFLIMIT = (dst_end - MFLIMIT);
+
+ // Special case
+ if (src_p == src_end) goto _output_error; // A correctly formed null-compressed LZ4 must have at least one byte (token=0)
+
+ // Main Loop
+ while (true)
+ {
+ byte token;
+ int length;
+
+ // get runlength
+ token = src[src_p++];
+ if ((length = (token >> ML_BITS)) == RUN_MASK)
+ {
+ var s = 255;
+ while ((src_p < src_end) && (s == 255)) length += (s = src[src_p++]);
+ }
+
+ // copy literals
+ dst_cpy = dst_p + length;
+
+ if ((dst_cpy > dst_MFLIMIT) || (src_p + length > src_LASTLITERALS_3))
+ {
+ if (dst_cpy > dst_end) goto _output_error; // Error : writes beyond output buffer
+ if (src_p + length != src_end) goto _output_error; // Error : LZ4 format requires to consume all input at this stage (no match within the last 11 bytes, and at least 8 remaining input bytes for another match+literals)
+ BlockCopy(src, src_p, dst, dst_p, length);
+ dst_p += length;
+ break; // Necessarily EOF, due to parsing restrictions
+ }
+ if (dst_p < dst_cpy) /*?*/
+ {
+ _i = WildCopy(src, src_p, dst, dst_p, dst_cpy);
+ src_p += _i;
+ dst_p += _i;
+ }
+ src_p -= (dst_p - dst_cpy);
+ dst_p = dst_cpy;
+
+ // get offset
+ dst_ref = (dst_cpy) - Peek2(src, src_p);
+ src_p += 2;
+ if (dst_ref < dst_0) goto _output_error; // Error : offset outside of destination buffer
+
+ // get matchlength
+ if ((length = (token & ML_MASK)) == ML_MASK)
+ {
+ while (src_p < src_LASTLITERALS_1) // Error : a minimum input bytes must remain for LASTLITERALS + token
+ {
+ int s = src[src_p++];
+ length += s;
+ if (s == 255) continue;
+ break;
+ }
+ }
+
+ // copy repeated sequence
+ if (dst_p - dst_ref < STEPSIZE_64)
+ {
+ var dec64 = dec64table[dst_p - dst_ref];
+ dst[dst_p + 0] = dst[dst_ref + 0];
+ dst[dst_p + 1] = dst[dst_ref + 1];
+ dst[dst_p + 2] = dst[dst_ref + 2];
+ dst[dst_p + 3] = dst[dst_ref + 3];
+ dst_p += 4;
+ dst_ref += 4;
+ dst_ref -= dec32table[dst_p - dst_ref];
+ Copy4(dst, dst_ref, dst_p);
+ dst_p += STEPSIZE_64 - 4;
+ dst_ref -= dec64;
+ }
+ else
+ {
+ Copy8(dst, dst_ref, dst_p);
+ dst_p += 8;
+ dst_ref += 8;
+ }
+ dst_cpy = dst_p + length - (STEPSIZE_64 - 4);
+
+ if (dst_cpy > dst_COPYLENGTH_STEPSIZE_4)
+ {
+ if (dst_cpy > dst_LASTLITERALS) goto _output_error; // Error : last 5 bytes must be literals
+ if (dst_p < dst_COPYLENGTH)
+ {
+ _i = SecureCopy(dst, dst_ref, dst_p, dst_COPYLENGTH);
+ dst_ref += _i;
+ dst_p += _i;
+ }
+ while (dst_p < dst_cpy) dst[dst_p++] = dst[dst_ref++];
+ dst_p = dst_cpy;
+ continue;
+ }
+
+ if (dst_p < dst_cpy)
+ {
+ SecureCopy(dst, dst_ref, dst_p, dst_cpy);
+ }
+ dst_p = dst_cpy; // correction
+ }
+
+ // end of decoding
+ return ((dst_p) - dst_0);
+
+ // write overflow error detected
+ _output_error:
+ return (-((src_p) - src_0));
+ }
+
+ #endregion
+ }
+}
+
+// ReSharper restore RedundantIfElseBlock
+// ReSharper restore JoinDeclarationAndInitializer
+// ReSharper restore TooWideLocalVariableScope
+// ReSharper restore InconsistentNaming
+// ReSharper restore CheckNamespace
diff --git a/Assets/Scripts/LZ4/LZ4Codec.Safe64.Dirty.cs.meta b/Assets/Scripts/LZ4/LZ4Codec.Safe64.Dirty.cs.meta
new file mode 100644
index 0000000..bb791e8
--- /dev/null
+++ b/Assets/Scripts/LZ4/LZ4Codec.Safe64.Dirty.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 04fd67d662c762548a89d1fe5bf6cfcc
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/LZ4/LZ4Codec.Safe64HC.Dirty.cs b/Assets/Scripts/LZ4/LZ4Codec.Safe64HC.Dirty.cs
new file mode 100644
index 0000000..8ff946c
--- /dev/null
+++ b/Assets/Scripts/LZ4/LZ4Codec.Safe64HC.Dirty.cs
@@ -0,0 +1,526 @@
+#region LZ4 original
+
+/*
+ LZ4 - Fast LZ compression algorithm
+ Copyright (C) 2011-2012, Yann Collet.
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ You can contact the author at :
+ - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
+ - LZ4 source repository : http://code.google.com/p/lz4/
+*/
+
+#endregion
+
+#region LZ4 port
+
+/*
+Copyright (c) 2013, Milosz Krajewski
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided
+that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this list of conditions
+ and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
+ and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#endregion
+
+// ReSharper disable InconsistentNaming
+
+namespace LZ4ps
+{
+ public static partial class LZ4Codec
+ {
+ private static void LZ4HC_Insert_64(LZ4HC_Data_Structure ctx, int src_p)
+ {
+ var chainTable = ctx.chainTable;
+ var hashTable = ctx.hashTable;
+ var src = ctx.src;
+ var src_base = ctx.src_base;
+ var nextToUpdate = ctx.nextToUpdate;
+
+ while (nextToUpdate < src_p)
+ {
+ var p = nextToUpdate;
+ var delta = (p) - (hashTable[(((Peek4(src, p)) * 2654435761u) >> HASHHC_ADJUST)] + src_base);
+ if (delta > MAX_DISTANCE) delta = MAX_DISTANCE;
+ chainTable[(p) & MAXD_MASK] = (ushort)delta;
+ hashTable[(((Peek4(src, p)) * 2654435761u) >> HASHHC_ADJUST)] = ((p) - src_base);
+ nextToUpdate++;
+ }
+
+ ctx.nextToUpdate = nextToUpdate;
+ }
+
+ private static int LZ4HC_CommonLength_64(LZ4HC_Data_Structure ctx, int p1, int p2)
+ {
+ var debruijn64 = DEBRUIJN_TABLE_64;
+ var src = ctx.src;
+ var src_LASTLITERALS = ctx.src_LASTLITERALS;
+ var p1t = p1;
+
+ while (p1t < src_LASTLITERALS - (STEPSIZE_64 - 1))
+ {
+ var diff = (long)Xor8(src, p2, p1t);
+ if (diff == 0)
+ {
+ p1t += STEPSIZE_64;
+ p2 += STEPSIZE_64;
+ continue;
+ }
+ p1t += debruijn64[((ulong)((diff) & -(diff)) * 0x0218A392CDABBD3FL) >> 58];
+ return (p1t - p1);
+ }
+ if ((p1t < (src_LASTLITERALS - 3)) && (Equal4(src, p2, p1t)))
+ {
+ p1t += 4;
+ p2 += 4;
+ }
+ if ((p1t < (src_LASTLITERALS - 1)) && (Equal2(src, p2, p1t)))
+ {
+ p1t += 2;
+ p2 += 2;
+ }
+ if ((p1t < src_LASTLITERALS) && (src[p2] == src[p1t])) p1t++;
+ return (p1t - p1);
+ }
+
+ private static int LZ4HC_InsertAndFindBestMatch_64(LZ4HC_Data_Structure ctx, int src_p, ref int matchpos)
+ {
+ var chainTable = ctx.chainTable;
+ var hashTable = ctx.hashTable;
+ var src = ctx.src;
+ var src_base = ctx.src_base;
+ var nbAttempts = MAX_NB_ATTEMPTS;
+ int repl = 0, ml = 0;
+ ushort delta = 0;
+
+ // HC4 match finder
+ LZ4HC_Insert_64(ctx, src_p);
+ var src_ref = (hashTable[(((Peek4(src, src_p)) * 2654435761u) >> HASHHC_ADJUST)] + src_base);
+
+ // Detect repetitive sequences of length <= 4
+ if (src_ref >= src_p - 4) // potential repetition
+ {
+ if (Equal4(src, src_ref, src_p)) // confirmed
+ {
+ delta = (ushort)(src_p - src_ref);
+ repl = ml = LZ4HC_CommonLength_64(ctx, src_p + MINMATCH, src_ref + MINMATCH) + MINMATCH;
+ matchpos = src_ref;
+ }
+ src_ref = ((src_ref) - chainTable[(src_ref) & MAXD_MASK]);
+ }
+
+
+ while ((src_ref >= src_p - MAX_DISTANCE) && (nbAttempts != 0))
+ {
+ nbAttempts--;
+ if (src[src_ref + ml] == src[src_p + ml])
+ {
+ if (Equal4(src, src_ref, src_p))
+ {
+ var mlt = LZ4HC_CommonLength_64(ctx, src_p + MINMATCH, src_ref + MINMATCH) + MINMATCH;
+ if (mlt > ml)
+ {
+ ml = mlt;
+ matchpos = src_ref;
+ }
+ }
+ }
+ src_ref = ((src_ref) - chainTable[(src_ref) & MAXD_MASK]);
+ }
+
+
+ // Complete table
+ if (repl != 0)
+ {
+ var ptr = src_p;
+
+ var end = src_p + repl - (MINMATCH - 1);
+ while (ptr < end - delta)
+ {
+ chainTable[(ptr) & MAXD_MASK] = delta; // Pre-Load
+ ptr++;
+ }
+ do
+ {
+ chainTable[(ptr) & MAXD_MASK] = delta;
+ hashTable[(((Peek4(src, ptr)) * 2654435761u) >> HASHHC_ADJUST)] = ((ptr) - src_base); // Head of chain
+ ptr++;
+ } while (ptr < end);
+ ctx.nextToUpdate = end;
+ }
+
+ return ml;
+ }
+
+ private static int LZ4HC_InsertAndGetWiderMatch_64(LZ4HC_Data_Structure ctx, int src_p, int startLimit, int longest, ref int matchpos, ref int startpos)
+ {
+ var debruijn64 = DEBRUIJN_TABLE_64;
+ var chainTable = ctx.chainTable;
+ var hashTable = ctx.hashTable;
+ var src = ctx.src;
+ var src_base = ctx.src_base;
+ var src_LASTLITERALS = ctx.src_LASTLITERALS;
+ var nbAttempts = MAX_NB_ATTEMPTS;
+ var delta = (src_p - startLimit);
+
+ // First Match
+ LZ4HC_Insert_64(ctx, src_p);
+ var src_ref = (hashTable[(((Peek4(src, src_p)) * 2654435761u) >> HASHHC_ADJUST)] + src_base);
+
+ while ((src_ref >= src_p - MAX_DISTANCE) && (nbAttempts != 0))
+ {
+ nbAttempts--;
+ if (src[startLimit + longest] == src[src_ref - delta + longest])
+ {
+ if (Equal4(src, src_ref, src_p))
+ {
+ var reft = src_ref + MINMATCH;
+ var ipt = src_p + MINMATCH;
+ var startt = src_p;
+
+ while (ipt < src_LASTLITERALS - (STEPSIZE_64 - 1))
+ {
+ var diff = (long)Xor8(src, reft, ipt);
+ if (diff == 0)
+ {
+ ipt += STEPSIZE_64;
+ reft += STEPSIZE_64;
+ continue;
+ }
+ ipt += debruijn64[((ulong)((diff) & -(diff)) * 0x0218A392CDABBD3FL) >> 58];
+ goto _endCount;
+ }
+ if ((ipt < (src_LASTLITERALS - 3)) && (Equal4(src, reft, ipt)))
+ {
+ ipt += 4;
+ reft += 4;
+ }
+ if ((ipt < (src_LASTLITERALS - 1)) && (Equal2(src, reft, ipt)))
+ {
+ ipt += 2;
+ reft += 2;
+ }
+ if ((ipt < src_LASTLITERALS) && (src[reft] == src[ipt])) ipt++;
+
+ _endCount:
+ reft = src_ref;
+
+ while ((startt > startLimit) && (reft > src_base) && (src[startt - 1] == src[reft - 1]))
+ {
+ startt--;
+ reft--;
+ }
+
+ if ((ipt - startt) > longest)
+ {
+ longest = (ipt - startt);
+ matchpos = reft;
+ startpos = startt;
+ }
+ }
+ }
+ src_ref = ((src_ref) - chainTable[(src_ref) & MAXD_MASK]);
+ }
+
+ return longest;
+ }
+
+ private static int LZ4_encodeSequence_64(LZ4HC_Data_Structure ctx, ref int src_p, ref int dst_p, ref int src_anchor, int matchLength, int src_ref)
+ {
+ var src = ctx.src;
+ var dst = ctx.dst;
+ var dst_end = ctx.dst_end;
+ int len;
+
+ // Encode Literal length
+ var length = (src_p - src_anchor);
+ var dst_token = (dst_p)++;
+ if ((dst_p + length + (2 + 1 + LASTLITERALS) + (length >> 8)) > dst_end) return 1; // Check output limit
+ if (length >= RUN_MASK)
+ {
+ dst[dst_token] = (RUN_MASK << ML_BITS);
+ len = length - RUN_MASK;
+ for (; len > 254; len -= 255) dst[dst_p++] = 255;
+ dst[dst_p++] = (byte)len;
+ }
+ else
+ {
+ dst[dst_token] = (byte)(length << ML_BITS);
+ }
+
+ // Copy Literals
+ if (length > 0)
+ {
+ var _i = dst_p + length;
+ src_anchor += WildCopy(src, src_anchor, dst, dst_p, _i);
+ dst_p = _i;
+ }
+
+ // Encode Offset
+ Poke2(dst, dst_p, (ushort)(src_p - src_ref));
+ dst_p += 2;
+
+ // Encode MatchLength
+ len = (matchLength - MINMATCH);
+ if (dst_p + (1 + LASTLITERALS) + (length >> 8) > dst_end) return 1; // Check output limit
+ if (len >= ML_MASK)
+ {
+ dst[dst_token] += ML_MASK;
+ len -= ML_MASK;
+ for (; len > 509; len -= 510)
+ {
+ dst[dst_p++] = 255;
+ dst[dst_p++] = 255;
+ }
+ if (len > 254)
+ {
+ len -= 255;
+ dst[dst_p++] = 255;
+ }
+ dst[dst_p++] = (byte)len;
+ }
+ else
+ {
+ dst[dst_token] += (byte)len;
+ }
+
+ // Prepare next loop
+ src_p += matchLength;
+ src_anchor = src_p;
+
+ return 0;
+ }
+
+ private static int LZ4_compressHCCtx_64(LZ4HC_Data_Structure ctx)
+ {
+ var src = ctx.src;
+ var src_p = ctx.src_base;
+ var src_end = ctx.src_end;
+ var dst_0 = ctx.dst_base;
+ var src_anchor = src_p;
+ var src_mflimit = src_end - MFLIMIT;
+ var dst = ctx.dst;
+ var dst_len = ctx.dst_len;
+ var dst_p = ctx.dst_base;
+
+ var xxx_ref = 0;
+ var start2 = 0;
+ var ref2 = 0;
+ var start3 = 0;
+ var ref3 = 0;
+
+ src_p++;
+
+ // Main Loop
+ while (src_p < src_mflimit)
+ {
+ var ml = LZ4HC_InsertAndFindBestMatch_64(ctx, src_p, ref xxx_ref);
+ if (ml == 0)
+ {
+ src_p++;
+ continue;
+ }
+
+ // saved, in case we would skip too much
+ var start0 = src_p;
+ var ref0 = xxx_ref;
+ var ml0 = ml;
+
+ _Search2:
+ var ml2 = src_p + ml < src_mflimit
+ ? LZ4HC_InsertAndGetWiderMatch_64(ctx, src_p + ml - 2, src_p + 1, ml, ref ref2, ref start2)
+ : ml;
+
+ if (ml2 == ml) // No better match
+ {
+ if (LZ4_encodeSequence_64(ctx, ref src_p, ref dst_p, ref src_anchor, ml, xxx_ref) != 0) return 0;
+ continue;
+ }
+
+ if (start0 < src_p)
+ {
+ if (start2 < src_p + ml0) // empirical
+ {
+ src_p = start0;
+ xxx_ref = ref0;
+ ml = ml0;
+ }
+ }
+
+ // Here, start0==ip
+ if ((start2 - src_p) < 3) // First Match too small : removed
+ {
+ ml = ml2;
+ src_p = start2;
+ xxx_ref = ref2;
+ goto _Search2;
+ }
+
+ _Search3:
+ // Currently we have :
+ // ml2 > ml1, and
+ // ip1+3 <= ip2 (usually < ip1+ml1)
+ if ((start2 - src_p) < OPTIMAL_ML)
+ {
+ var new_ml = ml;
+ if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML;
+ if (src_p + new_ml > start2 + ml2 - MINMATCH) new_ml = (start2 - src_p) + ml2 - MINMATCH;
+ var correction = new_ml - (start2 - src_p);
+ if (correction > 0)
+ {
+ start2 += correction;
+ ref2 += correction;
+ ml2 -= correction;
+ }
+ }
+ // Now, we have start2 = ip+new_ml, with new_ml=min(ml, OPTIMAL_ML=18)
+
+ var ml3 = start2 + ml2 < src_mflimit
+ ? LZ4HC_InsertAndGetWiderMatch_64(ctx, start2 + ml2 - 3, start2, ml2, ref ref3, ref start3)
+ : ml2;
+
+ if (ml3 == ml2) // No better match : 2 sequences to encode
+ {
+ // ip & ref are known; Now for ml
+ if (start2 < src_p + ml) ml = (start2 - src_p);
+ // Now, encode 2 sequences
+ if (LZ4_encodeSequence_64(ctx, ref src_p, ref dst_p, ref src_anchor, ml, xxx_ref) != 0) return 0;
+ src_p = start2;
+ if (LZ4_encodeSequence_64(ctx, ref src_p, ref dst_p, ref src_anchor, ml2, ref2) != 0) return 0;
+ continue;
+ }
+
+ if (start3 < src_p + ml + 3) // Not enough space for match 2 : remove it
+ {
+ if (start3 >= (src_p + ml)) // can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1
+ {
+ if (start2 < src_p + ml)
+ {
+ var correction = (src_p + ml - start2);
+ start2 += correction;
+ ref2 += correction;
+ ml2 -= correction;
+ if (ml2 < MINMATCH)
+ {
+ start2 = start3;
+ ref2 = ref3;
+ ml2 = ml3;
+ }
+ }
+
+ if (LZ4_encodeSequence_64(ctx, ref src_p, ref dst_p, ref src_anchor, ml, xxx_ref) != 0) return 0;
+ src_p = start3;
+ xxx_ref = ref3;
+ ml = ml3;
+
+ start0 = start2;
+ ref0 = ref2;
+ ml0 = ml2;
+ goto _Search2;
+ }
+
+ start2 = start3;
+ ref2 = ref3;
+ ml2 = ml3;
+ goto _Search3;
+ }
+
+ // OK, now we have 3 ascending matches; let's write at least the first one
+ // ip & ref are known; Now for ml
+ if (start2 < src_p + ml)
+ {
+ if ((start2 - src_p) < ML_MASK)
+ {
+ if (ml > OPTIMAL_ML) ml = OPTIMAL_ML;
+ if (src_p + ml > start2 + ml2 - MINMATCH) ml = (start2 - src_p) + ml2 - MINMATCH;
+ var correction = ml - (start2 - src_p);
+ if (correction > 0)
+ {
+ start2 += correction;
+ ref2 += correction;
+ ml2 -= correction;
+ }
+ }
+ else
+ {
+ ml = (start2 - src_p);
+ }
+ }
+ if (LZ4_encodeSequence_64(ctx, ref src_p, ref dst_p, ref src_anchor, ml, xxx_ref) != 0) return 0;
+
+ src_p = start2;
+ xxx_ref = ref2;
+ ml = ml2;
+
+ start2 = start3;
+ ref2 = ref3;
+ ml2 = ml3;
+
+ goto _Search3;
+ }
+
+ // Encode Last Literals
+ {
+ var lastRun = (src_end - src_anchor);
+ if ((dst_p - dst_0) + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > (uint)dst_len) return 0; // Check output limit
+ if (lastRun >= RUN_MASK)
+ {
+ dst[dst_p++] = (RUN_MASK << ML_BITS);
+ lastRun -= RUN_MASK;
+ for (; lastRun > 254; lastRun -= 255) dst[dst_p++] = 255;
+ dst[dst_p++] = (byte)lastRun;
+ }
+ else
+ {
+ dst[dst_p++] = (byte)(lastRun << ML_BITS);
+ }
+ BlockCopy(src, src_anchor, dst, dst_p, src_end - src_anchor);
+ dst_p += src_end - src_anchor;
+ }
+
+ // End
+ return (dst_p - dst_0);
+ }
+ }
+}
+
+// ReSharper restore InconsistentNaming
diff --git a/Assets/Scripts/LZ4/LZ4Codec.Safe64HC.Dirty.cs.meta b/Assets/Scripts/LZ4/LZ4Codec.Safe64HC.Dirty.cs.meta
new file mode 100644
index 0000000..e6f49e8
--- /dev/null
+++ b/Assets/Scripts/LZ4/LZ4Codec.Safe64HC.Dirty.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c61e65caf96385a469be74084e2e1f00
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/LZ4/LZ4Codec.cs b/Assets/Scripts/LZ4/LZ4Codec.cs
new file mode 100644
index 0000000..5cdf315
--- /dev/null
+++ b/Assets/Scripts/LZ4/LZ4Codec.cs
@@ -0,0 +1,176 @@
+#region license
+
+/*
+Copyright (c) 2013, Milosz Krajewski
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided
+that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this list of conditions
+ and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
+ and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#endregion
+
+using System;
+
+/*
+NOTE:
+ This file is shared between LZ4pn and LZ4ps.
+ If you would like to modify this file please keep in mind that your changes will
+ affect both projects.
+ Use 'UNSAFE' conditional define to differentiate
+*/
+
+// ReSharper disable InconsistentNaming
+
+#if UNSAFE
+namespace LZ4pn
+#else
+namespace LZ4ps
+#endif
+{
+ public static partial class LZ4Codec
+ {
+ #region configuration
+
+ ///
+ /// Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
+ /// Increasing memory usage improves compression ratio
+ /// Reduced memory usage can improve speed, due to cache effect
+ /// Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
+ ///
+ private const int MEMORY_USAGE = 20;
+
+ ///
+ /// Decreasing this value will make the algorithm skip faster data segments considered "incompressible"
+ /// This may decrease compression ratio dramatically, but will be faster on incompressible data
+ /// Increasing this value will make the algorithm search more before declaring a segment "incompressible"
+ /// This could improve compression a bit, but will be slower on incompressible data
+ /// The default value (6) is recommended
+ ///
+ private const int NOTCOMPRESSIBLE_DETECTIONLEVEL = 6;
+
+#if !UNSAFE
+
+ /// Buffer length when Buffer.BlockCopy becomes faster than straight loop.
+ /// Please note that safe implementation REQUIRES it to be greater (not even equal) than 8.
+ private const int BLOCK_COPY_LIMIT = 16;
+
+#endif
+
+ #endregion
+
+ #region consts
+
+ private const int MINMATCH = 4;
+ #pragma warning disable 162
+ // ReSharper disable once UnreachableCode
+ private const int SKIPSTRENGTH =
+ NOTCOMPRESSIBLE_DETECTIONLEVEL > 2
+ ? NOTCOMPRESSIBLE_DETECTIONLEVEL
+ : 2;
+ #pragma warning restore 162
+ private const int COPYLENGTH = 8;
+ private const int LASTLITERALS = 5;
+ private const int MFLIMIT = COPYLENGTH + MINMATCH;
+ private const int MINLENGTH = MFLIMIT + 1;
+ private const int MAXD_LOG = 16;
+ private const int MAXD = 1 << MAXD_LOG;
+ private const int MAXD_MASK = MAXD - 1;
+ private const int MAX_DISTANCE = (1 << MAXD_LOG) - 1;
+ private const int ML_BITS = 4;
+ private const int ML_MASK = (1 << ML_BITS) - 1;
+ private const int RUN_BITS = 8 - ML_BITS;
+ private const int RUN_MASK = (1 << RUN_BITS) - 1;
+ private const int STEPSIZE_64 = 8;
+ private const int STEPSIZE_32 = 4;
+
+ private const int LZ4_64KLIMIT = (1 << 16) + (MFLIMIT - 1);
+
+ private const int HASH_LOG = MEMORY_USAGE - 2;
+ private const int HASH_TABLESIZE = 1 << HASH_LOG;
+ private const int HASH_ADJUST = (MINMATCH * 8) - HASH_LOG;
+
+ private const int HASH64K_LOG = HASH_LOG + 1;
+ private const int HASH64K_TABLESIZE = 1 << HASH64K_LOG;
+ private const int HASH64K_ADJUST = (MINMATCH * 8) - HASH64K_LOG;
+
+ private const int HASHHC_LOG = MAXD_LOG - 1;
+ private const int HASHHC_TABLESIZE = 1 << HASHHC_LOG;
+ private const int HASHHC_ADJUST = (MINMATCH * 8) - HASHHC_LOG;
+ //private const int HASHHC_MASK = HASHHC_TABLESIZE - 1;
+
+ private static readonly int[] DECODER_TABLE_32 = { 0, 3, 2, 3, 0, 0, 0, 0 };
+ private static readonly int[] DECODER_TABLE_64 = { 0, 0, 0, -1, 0, 1, 2, 3 };
+
+ private static readonly int[] DEBRUIJN_TABLE_32 = {
+ 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1,
+ 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1
+ };
+
+ private static readonly int[] DEBRUIJN_TABLE_64 = {
+ 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7,
+ 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7,
+ 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6,
+ 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7
+ };
+
+ private const int MAX_NB_ATTEMPTS = 256;
+ private const int OPTIMAL_ML = (ML_MASK - 1) + MINMATCH;
+
+ #endregion
+
+ #region public interface (common)
+
+ /// Gets maximum the length of the output.
+ /// Length of the input.
+ /// Maximum number of bytes needed for compressed buffer.
+ public static int MaximumOutputLength(int inputLength)
+ {
+ return inputLength + (inputLength / 255) + 16;
+ }
+
+ #endregion
+
+ #region internal interface (common)
+
+ internal static void CheckArguments(
+ byte[] input, int inputOffset, ref int inputLength,
+ byte[] output, int outputOffset, ref int outputLength)
+ {
+ if (inputLength < 0) inputLength = input.Length - inputOffset;
+ if (inputLength == 0)
+ {
+ outputLength = 0;
+ return;
+ }
+
+ if (input == null) throw new ArgumentNullException("input");
+ if (inputOffset < 0 || inputOffset + inputLength > input.Length)
+ throw new ArgumentException("inputOffset and inputLength are invalid for given input");
+
+ if (outputLength < 0) outputLength = output.Length - outputOffset;
+ if (output == null) throw new ArgumentNullException("output");
+ if (outputOffset < 0 || outputOffset + outputLength > output.Length)
+ throw new ArgumentException("outputOffset and outputLength are invalid for given output");
+ }
+
+ #endregion
+ }
+}
+
+// ReSharper restore InconsistentNaming
\ No newline at end of file
diff --git a/Assets/Scripts/LZ4/LZ4Codec.cs.meta b/Assets/Scripts/LZ4/LZ4Codec.cs.meta
new file mode 100644
index 0000000..ea0b563
--- /dev/null
+++ b/Assets/Scripts/LZ4/LZ4Codec.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 60265417a9a7cb346be1757b77ecdd37
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/LZ4/LZ4Util.cs b/Assets/Scripts/LZ4/LZ4Util.cs
new file mode 100644
index 0000000..de805dc
--- /dev/null
+++ b/Assets/Scripts/LZ4/LZ4Util.cs
@@ -0,0 +1,129 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+//using LZ4Sharp;
+using LZ4ps;
+
+namespace LZ4
+{
+ ///
+ /// 置換
+ ///
+ public class LZ4Util
+ {
+ public static byte[] decompress(byte[] indata)
+ {
+ int m_curPos = 4;
+ int token = (int)(indata[m_curPos - 4] | (indata[m_curPos - 3] << 8) | (indata[m_curPos - 2] << 16) | (indata[m_curPos - 1] << 24));
+ m_curPos += 4;
+ int decompSize = (int)(indata[m_curPos - 4] | (indata[m_curPos - 3] << 8) | (indata[m_curPos - 2] << 16) | (indata[m_curPos - 1] << 24));
+ m_curPos += 4;
+ int compSize = (int)(indata[m_curPos - 4] | (indata[m_curPos - 3] << 8) | (indata[m_curPos - 2] << 16) | (indata[m_curPos - 1] << 24));
+ m_curPos += 4;
+ int tmp4 = (int)(indata[m_curPos - 4] | (indata[m_curPos - 3] << 8) | (indata[m_curPos - 2] << 16) | (indata[m_curPos - 1] << 24));
+
+ //byte[] srcBytes = new byte[compSize];
+ //Array.Copy(indata, 0x10, srcBytes, 0, compSize);
+
+ if (IntPtr.Size == 4)
+ {
+ return LZ4Codec.Decode32(indata, 0x10, compSize, decompSize);
+ }
+ else
+ {
+ return LZ4Codec.Decode64(indata, 0x10, compSize, decompSize);
+ }
+ }
+ }
+ /*
+ public class LZ4Util
+ {
+
+ public static byte[] decompress(byte[] indata)
+ {
+ LZ4.BinaryReader r = new LZ4.BinaryReader(indata);
+
+ byte[] dec = decompress(r);
+
+ return dec;
+ }
+
+ public static byte[] decompress(BinaryReader r)
+ {
+ byte[] retArray;
+ var dataSize = 0;
+ var decompressedSize = 0;
+
+ var token = 0;
+ var sqSize = 0;
+ var matchSize = 0;
+ var offset = 0;
+ var retCurPos = 0;
+ var endPos = 0;
+
+ r.seekAbs(4);
+ decompressedSize = r.readIntLE();
+ dataSize = r.readIntLE();
+ endPos = dataSize + 16;
+ retArray = new byte[decompressedSize];
+
+ r.seekAbs(16);
+
+ //Start reading sequences
+ while (true)
+ {
+ //read the LiteralSize and the MatchSize
+ token = r.readByte();
+ sqSize = token >> 4;
+ matchSize = (token & 0x0F) + 4;
+ if (sqSize == 15)
+ sqSize += readAdditionalSize(r);
+
+ //copy the literal
+ r.copyBytes(retArray, retCurPos, sqSize);
+ retCurPos += sqSize;
+
+ if (r.getPos() >= endPos - 1)
+ break;
+
+ //read the offset
+ offset = r.readShortLE();
+
+ //read the additional MatchSize
+ if (matchSize == 19)
+ matchSize += readAdditionalSize(r);
+
+ //copy the match properly
+ if (matchSize > offset)
+ {
+ var matchPos = retCurPos - offset;
+ while (true)
+ {
+ Array.Copy(retArray, matchPos, retArray, retCurPos, offset);
+ retCurPos += offset;
+ matchSize -= offset;
+ if (matchSize < offset)
+ break;
+ }
+ }
+ Array.Copy(retArray, retCurPos - offset, retArray, retCurPos, matchSize);
+ retCurPos += matchSize;
+ }
+
+
+ return retArray;
+ }
+
+ public static int readAdditionalSize(BinaryReader reader)
+ {
+ var size = reader.readByte();
+ if (size == 255)
+ return size + readAdditionalSize(reader);
+ else
+ return size;
+ }
+ }
+ */
+}
diff --git a/Assets/Scripts/LZ4/LZ4Util.cs.meta b/Assets/Scripts/LZ4/LZ4Util.cs.meta
new file mode 100644
index 0000000..05ff99b
--- /dev/null
+++ b/Assets/Scripts/LZ4/LZ4Util.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a39980c7200b27b4b8357880848e8646
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/Test.cs b/Assets/Scripts/Test.cs
new file mode 100644
index 0000000..5bc6597
--- /dev/null
+++ b/Assets/Scripts/Test.cs
@@ -0,0 +1,40 @@
+using BaseNcoding;
+using System;
+using System.Security.Cryptography;
+using System.Text;
+using UnityEngine;
+
+namespace Assets.Editor.RootMotion
+{
+ public class Test : MonoBehaviour
+ {
+ private void Start()
+ {
+ SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
+ var str = CalHameString(sha, 1541716412357448819, 77, Encoding.UTF8.GetBytes("root"));
+ Debug.LogWarning($"{str} Length:{str.Length}");
+ Debug.LogWarning($"{"FN4II57IWE274AT5R45G2UE7XVMFDPBD"} Length:{"FN4II57IWE274AT5R45G2UE7XVMFDPBD".Length}");
+ }
+
+ public byte[] CalHame(SHA1CryptoServiceProvider sha1, ulong checksum, ulong size, byte[] name)
+ {
+ if (name == null) return null;
+ byte[] allbyte = new byte[name.Length + 16];
+ byte[] checksumByte = BitConverter.GetBytes(checksum);
+ byte[] sizeByte = BitConverter.GetBytes(size);
+ for(int i=0; i < 16; i++)
+ {
+ allbyte[i] = (i < 8 ? checksumByte[7 - i] : sizeByte[15 - i]);
+ }
+ Buffer.BlockCopy(name, 0, allbyte, 16, name.Length);
+ return sha1.ComputeHash(allbyte);
+ }
+
+ public string CalHameString(SHA1CryptoServiceProvider sha1, ulong checksum, ulong size, byte[] name)
+ {
+ var bytes = CalHame(sha1, checksum, size, name);
+ Base32 base32 = new Base32();
+ return base32.Encode(bytes);
+ }
+ }
+}
diff --git a/Assets/Scripts/Test.cs.meta b/Assets/Scripts/Test.cs.meta
new file mode 100644
index 0000000..c617097
--- /dev/null
+++ b/Assets/Scripts/Test.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 822adc4dd85200142901586dd5c697c6
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json
index 99b6b22..1ebb68e 100644
--- a/Packages/packages-lock.json
+++ b/Packages/packages-lock.json
@@ -5,7 +5,7 @@
"depth": 1,
"source": "registry",
"dependencies": {},
- "url": "https://packages.unity.com"
+ "url": "https://packages.unity.cn"
},
"com.unity.assetbundlebrowser": {
"version": "https://github.com/Unity-Technologies/AssetBundles-Browser.git",
@@ -21,14 +21,14 @@
"dependencies": {
"com.unity.services.core": "1.0.1"
},
- "url": "https://packages.unity.com"
+ "url": "https://packages.unity.cn"
},
"com.unity.ext.nunit": {
"version": "1.0.6",
"depth": 1,
"source": "registry",
"dependencies": {},
- "url": "https://packages.unity.com"
+ "url": "https://packages.unity.cn"
},
"com.unity.formats.fbx": {
"version": "4.1.2",
@@ -38,7 +38,7 @@
"com.unity.timeline": "1.5.2",
"com.autodesk.fbx": "4.1.1"
},
- "url": "https://packages.unity.com"
+ "url": "https://packages.unity.cn"
},
"com.unity.ide.rider": {
"version": "2.0.7",
@@ -47,7 +47,7 @@
"dependencies": {
"com.unity.test-framework": "1.1.1"
},
- "url": "https://packages.unity.com"
+ "url": "https://packages.unity.cn"
},
"com.unity.ide.visualstudio": {
"version": "2.0.16",
@@ -56,14 +56,14 @@
"dependencies": {
"com.unity.test-framework": "1.1.9"
},
- "url": "https://packages.unity.com"
+ "url": "https://packages.unity.cn"
},
"com.unity.ide.vscode": {
"version": "1.2.5",
"depth": 0,
"source": "registry",
"dependencies": {},
- "url": "https://packages.unity.com"
+ "url": "https://packages.unity.cn"
},
"com.unity.postprocessing": {
"version": "3.2.2",
@@ -72,7 +72,7 @@
"dependencies": {
"com.unity.modules.physics": "1.0.0"
},
- "url": "https://packages.unity.com"
+ "url": "https://packages.unity.cn"
},
"com.unity.services.core": {
"version": "1.0.1",
@@ -81,7 +81,7 @@
"dependencies": {
"com.unity.modules.unitywebrequest": "1.0.0"
},
- "url": "https://packages.unity.com"
+ "url": "https://packages.unity.cn"
},
"com.unity.test-framework": {
"version": "1.1.31",
@@ -92,7 +92,7 @@
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0"
},
- "url": "https://packages.unity.com"
+ "url": "https://packages.unity.cn"
},
"com.unity.textmeshpro": {
"version": "3.0.6",
@@ -101,7 +101,7 @@
"dependencies": {
"com.unity.ugui": "1.0.0"
},
- "url": "https://packages.unity.com"
+ "url": "https://packages.unity.cn"
},
"com.unity.timeline": {
"version": "1.5.2",
@@ -113,7 +113,7 @@
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.particlesystem": "1.0.0"
},
- "url": "https://packages.unity.com"
+ "url": "https://packages.unity.cn"
},
"com.unity.ugui": {
"version": "1.0.0",
diff --git a/ProjectSettings/PackageManagerSettings.asset b/ProjectSettings/PackageManagerSettings.asset
index be4a797..bc93024 100644
--- a/ProjectSettings/PackageManagerSettings.asset
+++ b/ProjectSettings/PackageManagerSettings.asset
@@ -20,7 +20,7 @@ MonoBehaviour:
m_Registries:
- m_Id: main
m_Name:
- m_Url: https://packages.unity.com
+ m_Url: https://packages.unity.cn
m_Scopes: []
m_IsDefault: 1
m_Capabilities: 7
diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt
index 3598ae5..9b8fc7a 100644
--- a/ProjectSettings/ProjectVersion.txt
+++ b/ProjectSettings/ProjectVersion.txt
@@ -1,2 +1,2 @@
-m_EditorVersion: 2020.3.28f1
-m_EditorVersionWithRevision: 2020.3.28f1 (f5400f52e03f)
+m_EditorVersion: 2020.3.24f1c2
+m_EditorVersionWithRevision: 2020.3.24f1c2 (f3616f7ef48a)