Changes Huffman to in-place & Adds CircularBuffer (#287)

- [X] Adds CircularBuffer
- [X] Updates Packet Encoding/Decoding
- [X] Changes Huffman to in-place

Bumps release version
This commit is contained in:
Kamron Batman 2020-10-25 12:54:37 -07:00 committed by GitHub
parent 3337cfa4e2
commit 293e691539
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 237 additions and 190 deletions

View file

@ -12,7 +12,7 @@ namespace Server.Network
private const int ValueIndex = 1;
// UO packets may not exceed 64kb in length
private const int BufferSize = 0x10000;
public const int BufferSize = 0x10000;
// Optimal compression ratio is 2 / 8; worst compression ratio is 11 / 8
private const int MinimalCodeLength = 2;
@ -61,170 +61,127 @@ namespace Server.Network
0x4, 0x00D
};
public static void Compress(ReadOnlySpan<byte> input, CircularBufferWriter output)
public static void Compress(CircularBuffer<byte> buffer, ref int length)
{
int inputCapacity = input.Length;
length = Compress(buffer, length, buffer);
}
if (inputCapacity > DefiniteOverflow)
public static int Compress(CircularBuffer<byte> input, int inputLength, CircularBuffer<byte> output)
{
if (inputLength > DefiniteOverflow)
{
return;
return 0;
}
int bitCount = 0;
int bitValue = 0;
int inputIdx = 0;
int outputIdx = 0;
while (inputIdx < inputCapacity)
while (inputIdx < inputLength)
{
int i = input[inputIdx++] << 1;
bitCount += _huffmanTable[i];
bitValue <<= _huffmanTable[i];
bitValue |= _huffmanTable[i + 1];
bitValue = (bitValue << _huffmanTable[i]) | _huffmanTable[i + 1];
while (bitCount >= 8)
{
bitCount -= 8;
if (output.Length < output.Position + 1)
if (output.Length < outputIdx + 1)
{
return;
return 0;
}
output.Write((byte)(bitValue >> bitCount));
output[outputIdx++] = (byte)(bitValue >> bitCount);
}
}
// terminal code
bitCount += _huffmanTable[0x200];
bitValue <<= _huffmanTable[0x200];
bitValue |= _huffmanTable[0x201];
bitValue = (bitValue << _huffmanTable[0x200]) | _huffmanTable[0x201];
// align on byte boundary
if ((bitCount & 7) != 0)
{
bitValue <<= (8 - (bitCount & 7));
bitCount += (8 - (bitCount & 7));
bitValue <<= 8 - (bitCount & 7);
bitCount += 8 - (bitCount & 7);
}
while (bitCount >= 8)
{
bitCount -= 8;
if (output.Length < output.Position + 1)
if (output.Length < outputIdx + 1)
{
return;
return 0;
}
output.Write((byte)(bitValue >> bitCount));
output[outputIdx++] = (byte)(bitValue >> bitCount);
}
return outputIdx;
}
public static unsafe void Compress(
ReadOnlySpan<byte> input, int offset, int count, Span<byte> output, out int length
)
public static int Compress(ReadOnlySpan<byte> input, Span<byte> output)
{
if (input == null)
if (input.Length > DefiniteOverflow)
{
throw new ArgumentNullException(nameof(input));
return 0;
}
if (offset < 0 || offset >= input.Length)
int bitCount = 0;
int bitValue = 0;
int inputIdx = 0;
int outputIdx = 0;
while (inputIdx < input.Length)
{
throw new ArgumentOutOfRangeException(nameof(offset));
}
int i = input[inputIdx++] << 1;
if (count < 0 || count > input.Length)
{
throw new ArgumentOutOfRangeException(nameof(count));
}
bitCount += _huffmanTable[i];
bitValue = (bitValue << _huffmanTable[i]) | _huffmanTable[i + 1];
if (input.Length - offset < count)
{
throw new ArgumentOutOfRangeException(nameof(offset));
}
length = 0;
if (count > DefiniteOverflow)
{
return;
}
var bitCount = 0;
var bitValue = 0;
fixed (int* pTable = _huffmanTable)
{
fixed (byte* pInputBuffer = input)
while (bitCount >= 8)
{
byte* pInput = pInputBuffer + offset, pInputEnd = pInput + count;
bitCount -= 8;
fixed (byte* pOutputBuffer = output)
if (output.Length < outputIdx + 1)
{
byte* pOutput = pOutputBuffer, pOutputEnd = pOutput + BufferSize;
int* pEntry;
while (pInput < pInputEnd)
{
pEntry = &pTable[*pInput++ << 1];
bitCount += pEntry[CountIndex];
bitValue <<= pEntry[CountIndex];
bitValue |= pEntry[ValueIndex];
while (bitCount >= 8)
{
bitCount -= 8;
if (pOutput < pOutputEnd)
{
*pOutput++ = (byte)(bitValue >> bitCount);
}
else
{
length = 0;
return;
}
}
}
// terminal code
pEntry = &pTable[0x200];
bitCount += pEntry[CountIndex];
bitValue <<= pEntry[CountIndex];
bitValue |= pEntry[ValueIndex];
// align on byte boundary
if ((bitCount & 7) != 0)
{
bitValue <<= 8 - (bitCount & 7);
bitCount += 8 - (bitCount & 7);
}
while (bitCount >= 8)
{
bitCount -= 8;
if (pOutput < pOutputEnd)
{
*pOutput++ = (byte)(bitValue >> bitCount);
}
else
{
length = 0;
return;
}
}
length = (int)(pOutput - pOutputBuffer);
return 0;
}
output[outputIdx++] = (byte)(bitValue >> bitCount);
}
}
// terminal code
bitCount += _huffmanTable[0x200];
bitValue = (bitValue << _huffmanTable[0x200]) | _huffmanTable[0x201];
// align on byte boundary
if ((bitCount & 7) != 0)
{
bitValue <<= 8 - (bitCount & 7);
bitCount += 8 - (bitCount & 7);
}
while (bitCount >= 8)
{
bitCount -= 8;
if (output.Length < outputIdx + 1)
{
return 0;
}
output[outputIdx++] = (byte)(bitValue >> bitCount);
}
return outputIdx;
}
}
}