Files
UltimateFishing/Assets/Scripts/Assembly-CSharp/Unity/IO/Compression/HuffmanTree.cs
2026-02-21 16:45:37 +08:00

216 lines
4.2 KiB
C#

namespace Unity.IO.Compression
{
internal class HuffmanTree
{
internal const int MaxLiteralTreeElements = 288;
internal const int MaxDistTreeElements = 32;
internal const int EndOfBlockCode = 256;
internal const int NumberOfCodeLengthTreeElements = 19;
private int tableBits;
private short[] table;
private short[] left;
private short[] right;
private byte[] codeLengthArray;
private int tableMask;
private static HuffmanTree staticLiteralLengthTree;
private static HuffmanTree staticDistanceTree;
public static HuffmanTree StaticLiteralLengthTree
{
get
{
return staticLiteralLengthTree;
}
}
public static HuffmanTree StaticDistanceTree
{
get
{
return staticDistanceTree;
}
}
static HuffmanTree()
{
staticLiteralLengthTree = new HuffmanTree(GetStaticLiteralTreeLength());
staticDistanceTree = new HuffmanTree(GetStaticDistanceTreeLength());
}
public HuffmanTree(byte[] codeLengths)
{
codeLengthArray = codeLengths;
if (codeLengthArray.Length == 288)
{
tableBits = 9;
}
else
{
tableBits = 7;
}
tableMask = (1 << tableBits) - 1;
CreateTable();
}
private static byte[] GetStaticLiteralTreeLength()
{
byte[] array = new byte[288];
for (int i = 0; i <= 143; i++)
{
array[i] = 8;
}
for (int j = 144; j <= 255; j++)
{
array[j] = 9;
}
for (int k = 256; k <= 279; k++)
{
array[k] = 7;
}
for (int l = 280; l <= 287; l++)
{
array[l] = 8;
}
return array;
}
private static byte[] GetStaticDistanceTreeLength()
{
byte[] array = new byte[32];
for (int i = 0; i < 32; i++)
{
array[i] = 5;
}
return array;
}
private uint[] CalculateHuffmanCode()
{
uint[] array = new uint[17];
byte[] array2 = codeLengthArray;
foreach (int num in array2)
{
array[num]++;
}
array[0] = 0u;
uint[] array3 = new uint[17];
uint num2 = 0u;
for (int j = 1; j <= 16; j++)
{
num2 = (array3[j] = num2 + array[j - 1] << 1);
}
uint[] array4 = new uint[288];
for (int k = 0; k < codeLengthArray.Length; k++)
{
int num3 = codeLengthArray[k];
if (num3 > 0)
{
array4[k] = FastEncoderStatics.BitReverse(array3[num3], num3);
array3[num3]++;
}
}
return array4;
}
private void CreateTable()
{
uint[] array = CalculateHuffmanCode();
table = new short[1 << tableBits];
left = new short[2 * codeLengthArray.Length];
right = new short[2 * codeLengthArray.Length];
short num = (short)codeLengthArray.Length;
for (int i = 0; i < codeLengthArray.Length; i++)
{
int num2 = codeLengthArray[i];
if (num2 <= 0)
{
continue;
}
int num3 = (int)array[i];
if (num2 <= tableBits)
{
int num4 = 1 << num2;
if (num3 >= num4)
{
throw new InvalidDataException(SR.GetString("Invalid Huffman data"));
}
int num5 = 1 << tableBits - num2;
for (int j = 0; j < num5; j++)
{
table[num3] = (short)i;
num3 += num4;
}
continue;
}
int num6 = num2 - tableBits;
int num7 = 1 << tableBits;
int num8 = num3 & ((1 << tableBits) - 1);
short[] array2 = table;
do
{
short num9 = array2[num8];
if (num9 == 0)
{
array2[num8] = (short)(-num);
num9 = (short)(-num);
num++;
}
if (num9 > 0)
{
throw new InvalidDataException(SR.GetString("Invalid Huffman data"));
}
array2 = (((num3 & num7) != 0) ? right : left);
num8 = -num9;
num7 <<= 1;
num6--;
}
while (num6 != 0);
array2[num8] = (short)i;
}
}
public int GetNextSymbol(InputBuffer input)
{
uint num = input.TryLoad16Bits();
if (input.AvailableBits == 0)
{
return -1;
}
int num2 = table[num & tableMask];
if (num2 < 0)
{
uint num3 = (uint)(1 << tableBits);
do
{
num2 = -num2;
num2 = (((num & num3) != 0) ? right[num2] : left[num2]);
num3 <<= 1;
}
while (num2 < 0);
}
int num4 = codeLengthArray[num2];
if (num4 <= 0)
{
throw new InvalidDataException(SR.GetString("Invalid Huffman data"));
}
if (num4 > input.AvailableBits)
{
return -1;
}
input.SkipBits(num4);
return num2;
}
}
}