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:
parent
3337cfa4e2
commit
293e691539
6 changed files with 237 additions and 190 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue