Merge branch 'mppc' of github.com:awakecoding/FreeRDP into mppc

This commit is contained in:
Marc-André Moreau
2014-03-10 10:06:03 -04:00
7 changed files with 1158 additions and 292 deletions

View File

@@ -29,10 +29,8 @@ struct _MPPC_CONTEXT
{
wBitStream* bs;
BOOL Compressor;
UINT32 HistoryPtr;
BYTE* pHistoryPtr;
BYTE* HistoryPtr;
UINT32 HistoryOffset;
BYTE* pHistoryOffset;
UINT32 HistoryBufferSize;
BYTE HistoryBuffer[65536];
UINT16 MatchBuffer[32768];
@@ -45,6 +43,7 @@ extern "C" {
#endif
FREERDP_API UINT32 mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE* pDstData, UINT32* pSize);
FREERDP_API UINT32 mppc_decompress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE** ppDstData, UINT32* pSize, UINT32 flags);
FREERDP_API MPPC_CONTEXT* mppc_context_new(DWORD CompressionLevel, BOOL Compressor);
FREERDP_API void mppc_context_free(MPPC_CONTEXT* mppc);

View File

@@ -24,7 +24,7 @@
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/stream.h>
#include <winpr/collections.h>
#include <winpr/bitstream.h>
#include <freerdp/codec/mppc_enc.h>
#include <freerdp/codec/mppc_dec.h>
@@ -72,271 +72,675 @@ const UINT32 MPPC_MATCH_TABLE[256] =
//#define DEBUG_MPPC 1
UINT32 mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE* pDstData, UINT32* pSize)
UINT32 mppc_decompress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE** ppDstData, UINT32* pSize, UINT32 flags)
{
BYTE* pEnd;
UINT32 Flags;
BYTE* pMatch;
UINT32 MatchIndex;
BYTE Literal;
BYTE* SrcPtr;
UINT32 CopyOffset;
UINT32 LengthOfMatch;
UINT32 accumulator;
BYTE* HistoryBuffer;
BYTE* HistoryPtr;
UINT32 HistoryOffset;
UINT32 CompressionLevel;
wBitStream* bs = mppc->bs;
Flags = mppc->CompressionLevel;
HistoryBuffer = mppc->HistoryBuffer;
CompressionLevel = mppc->CompressionLevel;
BitStream_Attach(mppc->bs, pDstData, *pSize);
*ppDstData = HistoryBuffer;
if (((mppc->HistoryOffset + *pSize) < (mppc->HistoryBufferSize - 3)) /* && mppc->HistoryOffset */)
BitStream_Attach(bs, pSrcData, *pSize);
BitStream_Fetch(bs);
if (flags & PACKET_AT_FRONT)
{
/* SrcData fits into HistoryBuffer? (YES) */
CopyMemory(&(mppc->HistoryBuffer[mppc->HistoryOffset]), pSrcData, *pSize);
mppc->HistoryPtr = 0;
mppc->pHistoryPtr = &(mppc->HistoryBuffer[mppc->HistoryPtr]);
mppc->HistoryOffset += *pSize;
mppc->pHistoryOffset = &(mppc->HistoryBuffer[mppc->HistoryOffset]);
}
else
{
/* SrcData fits into HistoryBuffer? (NO) */
mppc->HistoryOffset = 0;
mppc->pHistoryOffset = &(mppc->HistoryBuffer[mppc->HistoryOffset]);
Flags |= PACKET_AT_FRONT;
mppc->HistoryPtr = &(HistoryBuffer[0]);
}
if (mppc->HistoryPtr < mppc->HistoryOffset)
if (flags & PACKET_FLUSHED)
{
/* HistoryPtr < HistoryOffset? (YES) */
mppc->HistoryPtr = &(HistoryBuffer[0]);
ZeroMemory(HistoryBuffer, mppc->HistoryBufferSize);
}
/*
* Search for a match of at least 3 bytes from the start of the history buffer
* to (HistoryPtr - 1) for the data that immediately follows HistoryPtr
if (!(flags & PACKET_COMPRESSED))
{
CopyMemory(mppc->HistoryPtr, pSrcData, *pSize);
mppc->HistoryPtr += *pSize;
return 0;
}
HistoryPtr = mppc->HistoryPtr;
HistoryOffset = mppc->HistoryOffset;
while ((bs->length - bs->position) >= 8)
{
accumulator = bs->accumulator;
/**
* Literal Encoding
*/
mppc->HistoryPtr = 0;
mppc->pHistoryPtr = &(mppc->HistoryBuffer[mppc->HistoryPtr]);
pEnd = &(mppc->HistoryBuffer[*pSize - 1]);
while (mppc->pHistoryPtr < (pEnd - 2))
if ((accumulator & 0x80000000) == 0x00000000)
{
MatchIndex = MPPC_MATCH_INDEX(mppc->pHistoryPtr[0], mppc->pHistoryPtr[1], mppc->pHistoryPtr[2]);
/**
* Literal, less than 0x80
* bit 0 followed by the lower 7 bits of the literal
*/
pMatch = &(mppc->HistoryBuffer[mppc->MatchBuffer[MatchIndex]]);
Literal = ((accumulator & 0x7F000000) >> 24);
mppc->MatchBuffer[MatchIndex] = (UINT16) mppc->HistoryPtr;
*(HistoryPtr) = Literal;
HistoryPtr++;
if ((mppc->pHistoryPtr[0] != pMatch[0]) || (mppc->pHistoryPtr[1] != pMatch[1]) ||
(mppc->pHistoryPtr[2] != pMatch[2]) || (mppc->pHistoryPtr == pMatch))
BitStream_Shift(bs, 8);
continue;
}
else if ((accumulator & 0xC0000000) == 0x80000000)
{
/**
* Literal, greater than 0x7F
* bits 10 followed by the lower 7 bits of the literal
*/
Literal = ((accumulator & 0x3F800000) >> 23) + 0x80;
*(HistoryPtr) = Literal;
HistoryPtr++;
BitStream_Shift(bs, 9);
continue;
}
/**
* CopyOffset Encoding
*/
CopyOffset = 0;
if (CompressionLevel) /* RDP5 */
{
if ((accumulator & 0xF8000000) == 0xF8000000)
{
accumulator = *(mppc->pHistoryPtr);
/**
* CopyOffset, range [0, 63]
* bits 11111 + lower 6 bits of CopyOffset
*/
#ifdef DEBUG_MPPC
printf("0x%02X", accumulator);
#endif
CopyOffset = ((accumulator >> 21) & 0x3F);
BitStream_Shift(bs, 11);
}
else if ((accumulator & 0xF8000000) == 0xF0000000)
{
/**
* CopyOffset, range [64, 319]
* bits 11110 + lower 8 bits of (CopyOffset - 64)
*/
if (accumulator < 0x80)
{
/* 8 bits of literal are encoded as-is */
BitStream_Write_Bits(mppc->bs, accumulator, 8);
}
else
{
/* bits 10 followed by lower 7 bits of literal */
accumulator = 0x100 | (accumulator & 0x7F);
BitStream_Write_Bits(mppc->bs, accumulator, 9);
}
CopyOffset = ((accumulator >> 19) & 0xFF) + 64;
BitStream_Shift(bs, 13);
}
else if ((accumulator & 0xF0000000) == 0xE0000000)
{
/**
* CopyOffset, range [320, 2367]
* bits 1110 + lower 11 bits of (CopyOffset - 320)
*/
mppc->HistoryPtr++;
mppc->pHistoryPtr = &(mppc->HistoryBuffer[mppc->HistoryPtr]);
CopyOffset = ((accumulator >> 17) & 0x7FF) + 320;
BitStream_Shift(bs, 15);
}
else if ((accumulator & 0xE0000000) == 0xC0000000)
{
/**
* CopyOffset, range [2368, ]
* bits 110 + lower 16 bits of (CopyOffset - 2368)
*/
CopyOffset = ((accumulator >> 13) & 0xFFFF) + 2368;
BitStream_Shift(bs, 19);
}
else
{
DWORD CopyOffset;
DWORD LengthOfMatch = 1;
/* Invalid CopyOffset Encoding */
}
}
else /* RDP4 */
{
if ((accumulator & 0xF0000000) == 0xF0000000)
{
/**
* CopyOffset, range [0, 63]
* bits 1111 + lower 6 bits of CopyOffset
*/
CopyOffset = (DWORD) (mppc->pHistoryPtr - pMatch);
CopyOffset = ((accumulator >> 22) & 0x3F);
BitStream_Shift(bs, 10);
}
else if ((accumulator & 0xF0000000) == 0xE0000000)
{
/**
* CopyOffset, range [64, 319]
* bits 1110 + lower 8 bits of (CopyOffset - 64)
*/
while ((mppc->pHistoryPtr[LengthOfMatch] == pMatch[LengthOfMatch]) &&
((mppc->HistoryPtr + LengthOfMatch) < (*pSize - 1)))
{
MatchIndex = MPPC_MATCH_INDEX(mppc->pHistoryPtr[LengthOfMatch],
mppc->pHistoryPtr[LengthOfMatch + 1], mppc->pHistoryPtr[LengthOfMatch + 2]);
CopyOffset = ((accumulator >> 20) & 0xFF) + 64;
BitStream_Shift(bs, 12);
}
else if ((accumulator & 0xE0000000) == 0xC0000000)
{
/**
* CopyOffset, range [320, 8191]
* bits 110 + lower 13 bits of (CopyOffset - 320)
*/
mppc->MatchBuffer[MatchIndex] = (UINT16) (mppc->HistoryPtr + LengthOfMatch);
LengthOfMatch++;
}
#ifdef DEBUG_MPPC
printf("<%d,%d>", (int) CopyOffset, (int) LengthOfMatch);
#endif
/* Encode CopyOffset */
if (CopyOffset < 64)
{
/* 11111 + lower 6 bits of CopyOffset */
accumulator = 0x07C0 | (CopyOffset & 0x003F);
BitStream_Write_Bits(mppc->bs, accumulator, 11);
}
else if ((CopyOffset >= 64) && (CopyOffset < 320))
{
/* 11110 + lower 8 bits of (CopyOffset - 64) */
accumulator = 0x1E00 | ((CopyOffset - 64) & 0x00FF);
BitStream_Write_Bits(mppc->bs, accumulator, 13);
}
else if ((CopyOffset >= 320) && (CopyOffset < 2368))
{
/* 1110 + lower 11 bits of (CopyOffset - 320) */
accumulator = 0x7000 | ((CopyOffset - 320) & 0x07FF);
BitStream_Write_Bits(mppc->bs, accumulator, 15);
}
else
{
/* 110 + lower 16 bits of (CopyOffset - 2368) */
accumulator = 0x060000 | ((CopyOffset - 2368) & 0xFFFF);
BitStream_Write_Bits(mppc->bs, accumulator, 19);
}
/* Encode LengthOfMatch */
if (LengthOfMatch == 3)
{
/* 0 + 0 lower bits of LengthOfMatch */
BitStream_Write_Bits(mppc->bs, 0, 1);
}
else if ((LengthOfMatch >= 4) && (LengthOfMatch < 8))
{
/* 10 + 2 lower bits of LengthOfMatch */
accumulator = 0x0008 | (LengthOfMatch & 0x0003);
BitStream_Write_Bits(mppc->bs, accumulator, 4);
}
else if ((LengthOfMatch >= 8) && (LengthOfMatch < 16))
{
/* 110 + 3 lower bits of LengthOfMatch */
accumulator = 0x0030 | (LengthOfMatch & 0x0007);
BitStream_Write_Bits(mppc->bs, accumulator, 6);
}
else if ((LengthOfMatch >= 16) && (LengthOfMatch < 32))
{
/* 1110 + 4 lower bits of LengthOfMatch */
accumulator = 0x00E0 | (LengthOfMatch & 0x000F);
BitStream_Write_Bits(mppc->bs, accumulator, 8);
}
else if ((LengthOfMatch >= 32) && (LengthOfMatch < 64))
{
/* 11110 + 5 lower bits of LengthOfMatch */
accumulator = 0x03C0 | (LengthOfMatch & 0x001F);
BitStream_Write_Bits(mppc->bs, accumulator, 10);
}
else if ((LengthOfMatch >= 64) && (LengthOfMatch < 128))
{
/* 111110 + 6 lower bits of LengthOfMatch */
accumulator = 0x0F80 | (LengthOfMatch & 0x003F);
BitStream_Write_Bits(mppc->bs, accumulator, 12);
}
else if ((LengthOfMatch >= 128) && (LengthOfMatch < 256))
{
/* 1111110 + 7 lower bits of LengthOfMatch */
accumulator = 0x3F00 | (LengthOfMatch & 0x007F);
BitStream_Write_Bits(mppc->bs, accumulator, 14);
}
else if ((LengthOfMatch >= 256) && (LengthOfMatch < 512))
{
/* 11111110 + 8 lower bits of LengthOfMatch */
accumulator = 0xFE00 | (LengthOfMatch & 0x00FF);
BitStream_Write_Bits(mppc->bs, accumulator, 16);
}
else if ((LengthOfMatch >= 512) && (LengthOfMatch < 1024))
{
/* 111111110 + 9 lower bits of LengthOfMatch */
accumulator = 0x3FC00 | (LengthOfMatch & 0x01FF);
BitStream_Write_Bits(mppc->bs, accumulator, 18);
}
else if ((LengthOfMatch >= 1024) && (LengthOfMatch < 2048))
{
/* 1111111110 + 10 lower bits of LengthOfMatch */
accumulator = 0xFF800 | (LengthOfMatch & 0x03FF);
BitStream_Write_Bits(mppc->bs, accumulator, 20);
}
else if ((LengthOfMatch >= 2048) && (LengthOfMatch < 4096))
{
/* 11111111110 + 11 lower bits of LengthOfMatch */
accumulator = 0x3FF000 | (LengthOfMatch & 0x07FF);
BitStream_Write_Bits(mppc->bs, accumulator, 22);
}
else if ((LengthOfMatch >= 4096) && (LengthOfMatch < 8192))
{
/* 111111111110 + 12 lower bits of LengthOfMatch */
accumulator = 0xFFE000 | (LengthOfMatch & 0x0FFF);
BitStream_Write_Bits(mppc->bs, accumulator, 24);
}
else if ((LengthOfMatch >= 8192) && (LengthOfMatch < 16384))
{
/* 1111111111110 + 13 lower bits of LengthOfMatch */
accumulator = 0x3FFC000 | (LengthOfMatch & 0x1FFF);
BitStream_Write_Bits(mppc->bs, accumulator, 26);
}
else if ((LengthOfMatch >= 16384) && (LengthOfMatch < 32768))
{
/* 11111111111110 + 14 lower bits of LengthOfMatch */
accumulator = 0xFFF8000 | (LengthOfMatch & 0x3FFF);
BitStream_Write_Bits(mppc->bs, accumulator, 28);
}
else if ((LengthOfMatch >= 32768) && (LengthOfMatch < 65536))
{
/* 111111111111110 + 15 lower bits of LengthOfMatch */
accumulator = 0x3FFF0000 | (LengthOfMatch & 0x7FFF);
BitStream_Write_Bits(mppc->bs, accumulator, 30);
}
mppc->HistoryPtr += LengthOfMatch;
mppc->pHistoryPtr += LengthOfMatch;
CopyOffset = ((accumulator >> 16) & 0x1FFF) + 320;
BitStream_Shift(bs, 16);
}
else
{
/* Invalid CopyOffset Encoding */
}
}
/* Encode trailing symbols as literals */
/**
* LengthOfMatch Encoding
*/
while (mppc->pHistoryPtr <= pEnd)
LengthOfMatch = 0;
accumulator = bs->accumulator;
if ((accumulator & 0x80000000) == 0x00000000)
{
MatchIndex = MPPC_MATCH_INDEX(mppc->pHistoryPtr[0], mppc->pHistoryPtr[1], mppc->pHistoryPtr[2]);
/**
* LengthOfMatch [3]
* bit 0 + 0 lower bits of LengthOfMatch
*/
pMatch = &(mppc->HistoryBuffer[mppc->MatchBuffer[MatchIndex]]);
LengthOfMatch = 3;
BitStream_Shift(bs, 1);
}
else if ((accumulator & 0xC0000000) == 0x80000000)
{
/**
* LengthOfMatch [4, 7]
* bits 10 + 2 lower bits of LengthOfMatch
*/
mppc->MatchBuffer[MatchIndex] = (UINT16) mppc->HistoryPtr;
LengthOfMatch = ((accumulator >> 28) & 0x0003) + 0x0004;
BitStream_Shift(bs, 4);
}
else if ((accumulator & 0xE0000000) == 0xC0000000)
{
/**
* LengthOfMatch [8, 15]
* bits 110 + 3 lower bits of LengthOfMatch
*/
accumulator = *(mppc->pHistoryPtr);
LengthOfMatch = ((accumulator >> 26) & 0x0007) + 0x0008;
BitStream_Shift(bs, 6);
}
else if ((accumulator & 0xF0000000) == 0xE0000000)
{
/**
* LengthOfMatch [16, 31]
* bits 1110 + 4 lower bits of LengthOfMatch
*/
LengthOfMatch = ((accumulator >> 24) & 0x000F) + 0x0010;
BitStream_Shift(bs, 8);
}
else if ((accumulator & 0xF8000000) == 0xF0000000)
{
/**
* LengthOfMatch [32, 63]
* bits 11110 + 5 lower bits of LengthOfMatch
*/
LengthOfMatch = ((accumulator >> 22) & 0x001F) + 0x0020;
BitStream_Shift(bs, 10);
}
else if ((accumulator & 0xFC000000) == 0xF8000000)
{
/**
* LengthOfMatch [64, 127]
* bits 111110 + 6 lower bits of LengthOfMatch
*/
LengthOfMatch = ((accumulator >> 20) & 0x003F) + 0x0040;
BitStream_Shift(bs, 12);
}
else if ((accumulator & 0xFE000000) == 0xFC000000)
{
/**
* LengthOfMatch [128, 255]
* bits 1111110 + 7 lower bits of LengthOfMatch
*/
LengthOfMatch = ((accumulator >> 18) & 0x007F) + 0x0080;
BitStream_Shift(bs, 14);
}
else if ((accumulator & 0xFF000000) == 0xFE000000)
{
/**
* LengthOfMatch [256, 511]
* bits 11111110 + 8 lower bits of LengthOfMatch
*/
LengthOfMatch = ((accumulator >> 16) & 0x00FF) + 0x0100;
BitStream_Shift(bs, 16);
}
else if ((accumulator & 0xFF800000) == 0xFF000000)
{
/**
* LengthOfMatch [512, 1023]
* bits 111111110 + 9 lower bits of LengthOfMatch
*/
LengthOfMatch = ((accumulator >> 14) & 0x01FF) + 0x0200;
BitStream_Shift(bs, 18);
}
else if ((accumulator & 0xFFC00000) == 0xFF800000)
{
/**
* LengthOfMatch [1024, 2047]
* bits 1111111110 + 10 lower bits of LengthOfMatch
*/
LengthOfMatch = ((accumulator >> 12) & 0x03FF) + 0x0400;
BitStream_Shift(bs, 20);
}
else if ((accumulator & 0xFFE00000) == 0xFFC00000)
{
/**
* LengthOfMatch [2048, 4095]
* bits 11111111110 + 11 lower bits of LengthOfMatch
*/
LengthOfMatch = ((accumulator >> 10) & 0x07FF) + 0x0800;
BitStream_Shift(bs, 22);
}
else if ((accumulator & 0xFFF00000) == 0xFFE00000)
{
/**
* LengthOfMatch [4096, 8191]
* bits 111111111110 + 12 lower bits of LengthOfMatch
*/
LengthOfMatch = ((accumulator >> 8) & 0x0FFF) + 0x1000;
BitStream_Shift(bs, 24);
}
else if (((accumulator & 0xFFF80000) == 0xFFF00000) && CompressionLevel) /* RDP5 */
{
/**
* LengthOfMatch [8192, 16383]
* bits 1111111111110 + 13 lower bits of LengthOfMatch
*/
LengthOfMatch = ((accumulator >> 6) & 0x1FFF) + 0x2000;
BitStream_Shift(bs, 26);
}
else if (((accumulator & 0xFFFC0000) == 0xFFF80000) && CompressionLevel) /* RDP5 */
{
/**
* LengthOfMatch [16384, 32767]
* bits 11111111111110 + 14 lower bits of LengthOfMatch
*/
LengthOfMatch = ((accumulator >> 4) & 0x3FFF) + 0x4000;
BitStream_Shift(bs, 28);
}
else if (((accumulator & 0xFFFE0000) == 0xFFFC0000) && CompressionLevel) /* RDP5 */
{
/**
* LengthOfMatch [32768, 65535]
* bits 111111111111110 + 15 lower bits of LengthOfMatch
*/
LengthOfMatch = ((accumulator >> 2) & 0x7FFF) + 0x8000;
BitStream_Shift(bs, 30);
}
else
{
/* Invalid LengthOfMatch Encoding */
}
#ifdef DEBUG_MPPC
printf("%c", accumulator);
printf("<%d,%d>\n", (int) CopyOffset, (int) LengthOfMatch);
#endif
SrcPtr = HistoryPtr - CopyOffset;
while (LengthOfMatch > 0)
{
*(HistoryPtr) = *SrcPtr;
HistoryPtr++;
SrcPtr++;
LengthOfMatch--;
}
}
*pSize = (UINT32) (HistoryPtr - mppc->HistoryPtr);
mppc->HistoryPtr = HistoryPtr;
return 0;
}
UINT32 mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE* pDstData, UINT32* pSize)
{
UINT32 Flags;
BYTE* pSrcEnd;
BYTE* pDstEnd;
BYTE* MatchPtr;
UINT32 MatchIndex;
UINT32 accumulator;
DWORD CopyOffset;
DWORD LengthOfMatch;
BYTE* HistoryBuffer;
BYTE* HistoryPtr;
UINT32 HistoryOffset;
UINT32 HistoryBufferSize;
UINT32 CompressionLevel;
wBitStream* bs = mppc->bs;
HistoryBuffer = mppc->HistoryBuffer;
HistoryBufferSize = mppc->HistoryBufferSize;
CompressionLevel = mppc->CompressionLevel;
HistoryPtr = mppc->HistoryPtr;
HistoryOffset = mppc->HistoryOffset;
BitStream_Attach(bs, pDstData, *pSize);
CopyMemory(&(HistoryBuffer[HistoryOffset]), pSrcData, *pSize);
if (((HistoryOffset + *pSize) < (HistoryBufferSize - 3)) && HistoryOffset)
{
Flags = 0;
}
else
{
HistoryOffset = 0;
Flags = PACKET_AT_FRONT;
}
HistoryPtr = &(HistoryBuffer[HistoryOffset]);
HistoryOffset += *pSize;
pSrcEnd = &(HistoryBuffer[*pSize - 1]);
pDstEnd = &(pDstData[*pSize - 1]);
while (HistoryPtr < (pSrcEnd - 2))
{
MatchIndex = MPPC_MATCH_INDEX(HistoryPtr[0], HistoryPtr[1], HistoryPtr[2]);
MatchPtr = &(HistoryBuffer[mppc->MatchBuffer[MatchIndex]]);
/* if (&MatchPtr[1] != HistoryPtr) */
mppc->MatchBuffer[MatchIndex] = (UINT16) (HistoryPtr - HistoryBuffer);
if (mppc->HistoryPtr < HistoryPtr)
mppc->HistoryPtr = HistoryPtr;
if ((HistoryPtr[0] != MatchPtr[0]) || (HistoryPtr[1] != MatchPtr[1]) ||
(HistoryPtr[2] != MatchPtr[2]) || (&MatchPtr[2] > mppc->HistoryPtr) ||
(MatchPtr == HistoryPtr) || (&MatchPtr[1] == HistoryPtr) ||
(MatchPtr == HistoryBuffer))
{
accumulator = *(HistoryPtr);
#ifdef DEBUG_MPPC
//printf("%c", accumulator);
#endif
if (((bs->position / 8) + 2) > (*pSize - 1))
{
Flags = PACKET_FLUSHED;
ZeroMemory(HistoryBuffer, HistoryBufferSize);
ZeroMemory(mppc->MatchBuffer, sizeof(mppc->MatchBuffer));
return Flags;
}
if (accumulator < 0x80)
{
/* 8 bits of literal are encoded as-is */
BitStream_Write_Bits(mppc->bs, accumulator, 8);
BitStream_Write_Bits(bs, accumulator, 8);
}
else
{
/* bits 10 followed by lower 7 bits of literal */
accumulator = 0x100 | (accumulator & 0x7F);
BitStream_Write_Bits(mppc->bs, accumulator, 9);
BitStream_Write_Bits(bs, accumulator, 9);
}
mppc->HistoryPtr++;
mppc->pHistoryPtr++;
HistoryPtr++;
}
else
{
LengthOfMatch = 3;
HistoryPtr += 3;
MatchPtr += 3;
CopyOffset = (HistoryBufferSize - 1) & (HistoryPtr - MatchPtr);
while ((*HistoryPtr == *MatchPtr) && /* (MatchPtr <= mppc->HistoryPtr) && */
((HistoryPtr - HistoryBuffer) < (*pSize - 1)))
{
LengthOfMatch++;
HistoryPtr++;
MatchPtr++;
}
#ifdef DEBUG_MPPC
printf("<%d,%d>\n", (int) CopyOffset, (int) LengthOfMatch);
#endif
/* Encode CopyOffset */
if (((bs->position / 8) + 7) > (*pSize - 1))
{
Flags = PACKET_FLUSHED;
ZeroMemory(HistoryBuffer, HistoryBufferSize);
ZeroMemory(mppc->MatchBuffer, sizeof(mppc->MatchBuffer));
return Flags;
}
if (CompressionLevel) /* RDP5 */
{
if (CopyOffset < 64)
{
/* bits 11111 + lower 6 bits of CopyOffset */
accumulator = 0x07C0 | (CopyOffset & 0x003F);
BitStream_Write_Bits(bs, accumulator, 11);
}
else if ((CopyOffset >= 64) && (CopyOffset < 320))
{
/* bits 11110 + lower 8 bits of (CopyOffset - 64) */
accumulator = 0x1E00 | ((CopyOffset - 64) & 0x00FF);
BitStream_Write_Bits(bs, accumulator, 13);
}
else if ((CopyOffset >= 320) && (CopyOffset < 2368))
{
/* bits 1110 + lower 11 bits of (CopyOffset - 320) */
accumulator = 0x7000 | ((CopyOffset - 320) & 0x07FF);
BitStream_Write_Bits(bs, accumulator, 15);
}
else
{
/* bits 110 + lower 16 bits of (CopyOffset - 2368) */
accumulator = 0x060000 | ((CopyOffset - 2368) & 0xFFFF);
BitStream_Write_Bits(bs, accumulator, 19);
}
}
else /* RDP4 */
{
if (CopyOffset < 64)
{
/* bits 1111 + lower 6 bits of CopyOffset */
accumulator = 0x03C0 | (CopyOffset & 0x003F);
BitStream_Write_Bits(bs, accumulator, 10);
}
else if ((CopyOffset >= 64) && (CopyOffset < 320))
{
/* bits 1110 + lower 8 bits of (CopyOffset - 64) */
accumulator = 0x0E00 | ((CopyOffset - 64) & 0x00FF);
BitStream_Write_Bits(bs, accumulator, 12);
}
else if ((CopyOffset >= 320) && (CopyOffset < 8192))
{
/* bits 110 + lower 13 bits of (CopyOffset - 320) */
accumulator = 0xC000 | ((CopyOffset - 320) & 0x1FFF);
BitStream_Write_Bits(bs, accumulator, 16);
}
}
/* Encode LengthOfMatch */
if (LengthOfMatch == 3)
{
/* 0 + 0 lower bits of LengthOfMatch */
BitStream_Write_Bits(bs, 0, 1);
}
else if ((LengthOfMatch >= 4) && (LengthOfMatch < 8))
{
/* 10 + 2 lower bits of LengthOfMatch */
accumulator = 0x0008 | (LengthOfMatch & 0x0003);
BitStream_Write_Bits(bs, accumulator, 4);
}
else if ((LengthOfMatch >= 8) && (LengthOfMatch < 16))
{
/* 110 + 3 lower bits of LengthOfMatch */
accumulator = 0x0030 | (LengthOfMatch & 0x0007);
BitStream_Write_Bits(bs, accumulator, 6);
}
else if ((LengthOfMatch >= 16) && (LengthOfMatch < 32))
{
/* 1110 + 4 lower bits of LengthOfMatch */
accumulator = 0x00E0 | (LengthOfMatch & 0x000F);
BitStream_Write_Bits(bs, accumulator, 8);
}
else if ((LengthOfMatch >= 32) && (LengthOfMatch < 64))
{
/* 11110 + 5 lower bits of LengthOfMatch */
accumulator = 0x03C0 | (LengthOfMatch & 0x001F);
BitStream_Write_Bits(bs, accumulator, 10);
}
else if ((LengthOfMatch >= 64) && (LengthOfMatch < 128))
{
/* 111110 + 6 lower bits of LengthOfMatch */
accumulator = 0x0F80 | (LengthOfMatch & 0x003F);
BitStream_Write_Bits(bs, accumulator, 12);
}
else if ((LengthOfMatch >= 128) && (LengthOfMatch < 256))
{
/* 1111110 + 7 lower bits of LengthOfMatch */
accumulator = 0x3F00 | (LengthOfMatch & 0x007F);
BitStream_Write_Bits(bs, accumulator, 14);
}
else if ((LengthOfMatch >= 256) && (LengthOfMatch < 512))
{
/* 11111110 + 8 lower bits of LengthOfMatch */
accumulator = 0xFE00 | (LengthOfMatch & 0x00FF);
BitStream_Write_Bits(bs, accumulator, 16);
}
else if ((LengthOfMatch >= 512) && (LengthOfMatch < 1024))
{
/* 111111110 + 9 lower bits of LengthOfMatch */
accumulator = 0x3FC00 | (LengthOfMatch & 0x01FF);
BitStream_Write_Bits(bs, accumulator, 18);
}
else if ((LengthOfMatch >= 1024) && (LengthOfMatch < 2048))
{
/* 1111111110 + 10 lower bits of LengthOfMatch */
accumulator = 0xFF800 | (LengthOfMatch & 0x03FF);
BitStream_Write_Bits(bs, accumulator, 20);
}
else if ((LengthOfMatch >= 2048) && (LengthOfMatch < 4096))
{
/* 11111111110 + 11 lower bits of LengthOfMatch */
accumulator = 0x3FF000 | (LengthOfMatch & 0x07FF);
BitStream_Write_Bits(bs, accumulator, 22);
}
else if ((LengthOfMatch >= 4096) && (LengthOfMatch < 8192))
{
/* 111111111110 + 12 lower bits of LengthOfMatch */
accumulator = 0xFFE000 | (LengthOfMatch & 0x0FFF);
BitStream_Write_Bits(bs, accumulator, 24);
}
else if (((LengthOfMatch >= 8192) && (LengthOfMatch < 16384)) && CompressionLevel) /* RDP5 */
{
/* 1111111111110 + 13 lower bits of LengthOfMatch */
accumulator = 0x3FFC000 | (LengthOfMatch & 0x1FFF);
BitStream_Write_Bits(bs, accumulator, 26);
}
else if (((LengthOfMatch >= 16384) && (LengthOfMatch < 32768)) && CompressionLevel) /* RDP5 */
{
/* 11111111111110 + 14 lower bits of LengthOfMatch */
accumulator = 0xFFF8000 | (LengthOfMatch & 0x3FFF);
BitStream_Write_Bits(bs, accumulator, 28);
}
else if (((LengthOfMatch >= 32768) && (LengthOfMatch < 65536)) && CompressionLevel) /* RDP5 */
{
/* 111111111111110 + 15 lower bits of LengthOfMatch */
accumulator = 0x3FFF0000 | (LengthOfMatch & 0x7FFF);
BitStream_Write_Bits(bs, accumulator, 30);
}
}
}
/* HistoryPtr < HistoryOffset? (NO) */
/* Encode trailing symbols as literals */
while (HistoryPtr <= pSrcEnd)
{
MatchIndex = MPPC_MATCH_INDEX(HistoryPtr[0], HistoryPtr[1], HistoryPtr[2]);
MatchPtr = &(HistoryBuffer[mppc->MatchBuffer[MatchIndex]]);
mppc->MatchBuffer[MatchIndex] = (UINT16) (HistoryPtr - HistoryBuffer);
accumulator = *(HistoryPtr);
#ifdef DEBUG_MPPC
//printf("%c", accumulator);
#endif
if (((bs->position / 8) + 2) > (*pSize - 1))
{
Flags = PACKET_FLUSHED;
ZeroMemory(HistoryBuffer, HistoryBufferSize);
ZeroMemory(mppc->MatchBuffer, sizeof(mppc->MatchBuffer));
return Flags;
}
if (accumulator < 0x80)
{
/* 8 bits of literal are encoded as-is */
BitStream_Write_Bits(bs, accumulator, 8);
}
else
{
/* bits 10 followed by lower 7 bits of literal */
accumulator = 0x100 | (accumulator & 0x7F);
BitStream_Write_Bits(bs, accumulator, 9);
}
HistoryPtr++;
}
BitStream_Flush(bs);
Flags |= PACKET_COMPRESSED;
*pSize = ((bs->position + 7) / 8);
BitStream_Flush(mppc->bs);
*pSize = (mppc->bs->position / 8);
mppc->HistoryPtr = HistoryPtr;
mppc->HistoryOffset = HistoryPtr - HistoryBuffer;
#ifdef DEBUG_MPPC
printf("\n");
#endif
return Flags;
}
@@ -366,6 +770,9 @@ MPPC_CONTEXT* mppc_context_new(DWORD CompressionLevel, BOOL Compressor)
ZeroMemory(&(mppc->MatchBuffer), sizeof(mppc->MatchBuffer));
mppc->bs = BitStream_New();
mppc->HistoryPtr = &(mppc->HistoryBuffer[0]);
mppc->HistoryOffset = 0;
}
return mppc;

View File

@@ -1,5 +1,6 @@
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/bitstream.h>
#include <freerdp/freerdp.h>
#include <freerdp/codec/mppc.h>
@@ -684,39 +685,375 @@ int test_mppc_old()
return 0;
}
const char TEST_MPPC_BELL_TOLLS[] = "for.whom.the.bell.tolls,.the.bell.tolls.for.thee!";
/**
*
* for.whom.the.bell.tolls,.the.bell.tolls.for.thee!
*
* for.whom.the.bell.tolls,<16,15>.<40,4><19,3>e! ([MS-RDPBCGR])
*
* <16,15> : ".the.bell.tolls"
* <40,4> : "for."
* <19,3> : "the"
*
* for.whom.the.bell.tolls,<16,15>.f<40,3><35,3>e! (Microsoft implementation)
*
* <16,15> : ".the.bell.tolls"
* <40,3> : "or."
* <19,3> " "the"
*
* RDP5:
* 01100110 Literal 'f'
* 01101111 Literal 'o'
* 01110010 Literal 'r'
* 00101110 Literal '.'
* 01110111 Literal 'w'
* 01101000 Literal 'h'
* 01101111 Literal 'o'
* 01101101 Literal 'm'
* 00101110 Literal '.'
* 01110100 Literal 't'
* 01101000 Literal 'h'
* 01100101 Literal 'e'
* 00101110 Literal '.'
* 01100010 Literal 'b'
* 01100101 Literal 'e'
* 01101100 Literal 'l'
* 01101100 Literal 'l'
* 00101110 Literal '.'
* 01110100 Literal 't'
* 01101111 Literal 'o'
* 01101100 Literal 'l'
* 01101100 Literal 'l'
* 01110011 Literal 's'
* 00101100 Literal ','
* 11111+010000 CopyOffset 16
* 110+111 LengthOfMatch 15
* 00101110 Literal '.'
* 01100110 Literal 'f'
* 11111+101000 CopyOffset 40
* 0 LengthOfMatch 3
* 11111+100011 CopyOffset 35
* 0 LengthOfMatch 3
* 01100101 Literal 'e'
* 00100001 Literal '!'
* 0000000 Trailing Bits
*
* RDP4:
* 01100110 Literal 'f'
* 01101111 Literal 'o'
* 01110010 Literal 'r'
* 00101110 Literal '.'
* 01110111 Literal 'w'
* 01101000 Literal 'h'
* 01101111 Literal 'o'
* 01101101 Literal 'm'
* 00101110 Literal '.'
* 01110100 Literal 't'
* 01101000 Literal 'h'
* 01100101 Literal 'e'
* 00101110 Literal '.'
* 01100010 Literal 'b'
* 01100101 Literal 'e'
* 01101100 Literal 'l'
* 01101100 Literal 'l'
* 00101110 Literal '.'
* 01110100 Literal 't'
* 01101111 Literal 'o'
* 01101100 Literal 'l'
* 01101100 Literal 'l'
* 01110011 Literal 's'
* 00101100 Literal ','
* 1111+010000 CopyOffset 16
* 110+111 LengthOfMatch 15
* 00101110 Literal '.'
* 01100110 Literal 'f'
* 1111+101000 CopyOffset 40
* 0 LengthOfMatch 3
* 1111+100011 CopyOffset 35
* 0 LengthOfMatch 3
* 01100101 Literal 'e'
* 00100001 Literal '!'
* 00 Trailing Bits
*/
int TestFreeRDPCodecMppc(int argc, char* argv[])
const BYTE TEST_MPPC_BELLS[] = "for.whom.the.bell.tolls,.the.bell.tolls.for.thee!";
/* Flags: 0x0060 Length: 33 */
const BYTE TEST_MPPC_BELLS_RDP4[] =
"\x66\x6f\x72\x2e\x77\x68\x6f\x6d\x2e\x74\x68\x65\x2e\x62\x65\x6c"
"\x6c\x2e\x74\x6f\x6c\x6c\x73\x2c\xf4\x37\x2e\x66\xfa\x1f\x19\x94"
"\x84";
/* Flags: 0x0061 Length: 34 */
const BYTE TEST_MPPC_BELLS_RDP5[] =
"\x66\x6f\x72\x2e\x77\x68\x6f\x6d\x2e\x74\x68\x65\x2e\x62\x65\x6c"
"\x6c\x2e\x74\x6f\x6c\x6c\x73\x2c\xfa\x1b\x97\x33\x7e\x87\xe3\x32"
"\x90\x80";
int test_MppcCompressBellsRdp5()
{
UINT32 size;
UINT32 flags;
BYTE* pSrcData;
MPPC_CONTEXT* mppc;
UINT32 expectedSize;
BYTE OutputBuffer[65536];
mppc = mppc_context_new(1, TRUE);
#if 0
size = sizeof(TEST_MPPC_BELL_TOLLS) - 1;
pSrcData = (BYTE*) TEST_MPPC_BELL_TOLLS;
printf("%s\n", pSrcData);
flags = mppc_compress(mppc, pSrcData, OutputBuffer, &size);
printf("flags: 0x%04X size: %d\n", flags, size);
#endif
size = sizeof(TEST_RDP5_UNCOMPRESSED_DATA);
pSrcData = (BYTE*) TEST_RDP5_UNCOMPRESSED_DATA;
size = sizeof(TEST_MPPC_BELLS) - 1;
pSrcData = (BYTE*) TEST_MPPC_BELLS;
expectedSize = sizeof(TEST_MPPC_BELLS_RDP5) - 1;
flags = mppc_compress(mppc, pSrcData, OutputBuffer, &size);
printf("flags: 0x%04X size: %d\n", flags, size);
winpr_HexDump(OutputBuffer, size);
//winpr_HexDump(TEST_RDP5_COMPRESSED_DATA, sizeof(TEST_RDP5_COMPRESSED_DATA));
if (size != expectedSize)
{
printf("MppcCompressBellsRdp5: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
return -1;
}
printf("sizeof(TEST_RDP5_COMPRESSED_DATA): %d\n", (int) sizeof(TEST_RDP5_COMPRESSED_DATA));
if (memcmp(OutputBuffer, TEST_MPPC_BELLS_RDP5, size) != 0)
{
printf("MppcCompressBellsRdp5: output mismatch\n");
printf("Actual\n");
BitDump(OutputBuffer, size * 8, 0);
printf("Expected\n");
BitDump(TEST_MPPC_BELLS_RDP5, size * 8, 0);
return -1;
}
mppc_context_free(mppc);
return 0;
}
int test_MppcCompressBellsRdp4()
{
UINT32 size;
UINT32 flags;
BYTE* pSrcData;
MPPC_CONTEXT* mppc;
UINT32 expectedSize;
BYTE OutputBuffer[65536];
mppc = mppc_context_new(0, TRUE);
size = sizeof(TEST_MPPC_BELLS) - 1;
pSrcData = (BYTE*) TEST_MPPC_BELLS;
expectedSize = sizeof(TEST_MPPC_BELLS_RDP4) - 1;
flags = mppc_compress(mppc, pSrcData, OutputBuffer, &size);
printf("flags: 0x%04X size: %d\n", flags, size);
if (size != expectedSize)
{
printf("MppcCompressBellsRdp4: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
return -1;
}
if (memcmp(OutputBuffer, TEST_MPPC_BELLS_RDP4, size) != 0)
{
printf("MppcCompressBellsRdp4: output mismatch\n");
printf("Actual\n");
BitDump(OutputBuffer, size * 8, 0);
printf("Expected\n");
BitDump(TEST_MPPC_BELLS_RDP4, size * 8, 0);
return -1;
}
mppc_context_free(mppc);
return 0;
}
int test_MppcDecompressBellsRdp5()
{
UINT32 size;
UINT32 flags;
BYTE* pSrcData;
MPPC_CONTEXT* mppc;
UINT32 expectedSize;
BYTE* pDstData = NULL;
mppc = mppc_context_new(1, FALSE);
size = sizeof(TEST_MPPC_BELLS_RDP5) - 1;
pSrcData = (BYTE*) TEST_MPPC_BELLS_RDP5;
flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 1;
expectedSize = sizeof(TEST_MPPC_BELLS) - 1;
flags = mppc_decompress(mppc, pSrcData, &pDstData, &size, flags);
printf("flags: 0x%04X size: %d\n", flags, size);
if (size != expectedSize)
{
printf("MppcDecompressBellsRdp5: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
return -1;
}
if (memcmp(pDstData, TEST_MPPC_BELLS, size) != 0)
{
printf("MppcDecompressBellsRdp5: output mismatch\n");
return -1;
}
mppc_context_free(mppc);
return 0;
}
int test_MppcDecompressBellsRdp4()
{
UINT32 size;
UINT32 flags;
BYTE* pSrcData;
MPPC_CONTEXT* mppc;
UINT32 expectedSize;
BYTE* pDstData = NULL;
mppc = mppc_context_new(0, FALSE);
size = sizeof(TEST_MPPC_BELLS_RDP4) - 1;
pSrcData = (BYTE*) TEST_MPPC_BELLS_RDP4;
flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 0;
expectedSize = sizeof(TEST_MPPC_BELLS) - 1;
flags = mppc_decompress(mppc, pSrcData, &pDstData, &size, flags);
printf("flags: 0x%04X size: %d\n", flags, size);
if (size != expectedSize)
{
printf("MppcDecompressBellsRdp4: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
return -1;
}
if (memcmp(pDstData, TEST_MPPC_BELLS, size) != 0)
{
printf("MppcDecompressBellsRdp4: output mismatch\n");
return -1;
}
mppc_context_free(mppc);
return 0;
}
int test_MppcCompressBufferRdp5()
{
UINT32 size;
UINT32 flags;
BYTE* pSrcData;
MPPC_CONTEXT* mppc;
UINT32 expectedSize;
BYTE OutputBuffer[65536];
MPPC_CONTEXT* mppcRecv;
BYTE* pDstData = NULL;
mppc = mppc_context_new(1, TRUE);
size = sizeof(TEST_RDP5_UNCOMPRESSED_DATA);
pSrcData = (BYTE*) TEST_RDP5_UNCOMPRESSED_DATA;
expectedSize = sizeof(TEST_RDP5_COMPRESSED_DATA);
flags = mppc_compress(mppc, pSrcData, OutputBuffer, &size);
printf("flags: 0x%04X size: %d\n", flags, size);
mppcRecv = mppc_context_new(1, FALSE);
pSrcData = (BYTE*) OutputBuffer;
flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 1;
expectedSize = sizeof(TEST_RDP5_UNCOMPRESSED_DATA);
flags = mppc_decompress(mppcRecv, pSrcData, &pDstData, &size, flags);
printf("flags: 0x%04X size: %d\n", flags, size);
if (size != expectedSize)
{
printf("MppcCompressBufferRdp5: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
return -1;
}
if (memcmp(pDstData, TEST_RDP5_UNCOMPRESSED_DATA, size) != 0)
{
printf("MppcCompressBufferRdp5: output mismatch: Decompress(Compress(X)) != X\n");
return -1;
}
mppc_context_free(mppc);
mppc_context_free(mppcRecv);
return 0;
}
int test_MppcDecompressBufferRdp5()
{
UINT32 size;
UINT32 flags;
BYTE* pSrcData;
MPPC_CONTEXT* mppc;
UINT32 expectedSize;
BYTE* pDstData = NULL;
mppc = mppc_context_new(1, FALSE);
size = sizeof(TEST_RDP5_COMPRESSED_DATA);
pSrcData = (BYTE*) TEST_RDP5_COMPRESSED_DATA;
flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 1;
expectedSize = sizeof(TEST_RDP5_UNCOMPRESSED_DATA);
flags = mppc_decompress(mppc, pSrcData, &pDstData, &size, flags);
printf("flags: 0x%04X size: %d\n", flags, size);
if (size != expectedSize)
{
printf("MppcDecompressBufferRdp5: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
return -1;
}
if (memcmp(pDstData, TEST_RDP5_UNCOMPRESSED_DATA, size) != 0)
{
printf("MppcDecompressBufferRdp5: output mismatch\n");
return -1;
}
mppc_context_free(mppc);
return 0;
}
int TestFreeRDPCodecMppc(int argc, char* argv[])
{
if (test_MppcCompressBellsRdp5() < 0)
return -1;
if (test_MppcDecompressBellsRdp5() < 0)
return -1;
if (test_MppcCompressBellsRdp4() < 0)
return -1;
if (test_MppcDecompressBellsRdp4() < 0)
return -1;
if (test_MppcCompressBufferRdp5() < 0)
return -1;
if (test_MppcDecompressBufferRdp5() < 0)
return -1;
//test_mppc_old();
return 0;
}

View File

@@ -0,0 +1,65 @@
/*
* WinPR: Windows Portable Runtime
* BitStream Utils
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_UTILS_BITSTREAM_H
#define WINPR_UTILS_BITSTREAM_H
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#include <winpr/crt.h>
struct _wBitStream
{
BYTE* buffer;
BYTE* pointer;
DWORD position;
DWORD length;
DWORD capacity;
UINT32 mask;
UINT32 offset;
UINT32 prefetch;
UINT32 accumulator;
};
typedef struct _wBitStream wBitStream;
#define BITDUMP_MSB_FIRST 0x00000001
#define BITDUMP_STDERR 0x00000002
#ifdef __cplusplus
extern "C" {
#endif
WINPR_API void BitStream_Attach(wBitStream* bs, BYTE* buffer, UINT32 capacity);
WINPR_API void BitStream_Write_Bits(wBitStream* bs, UINT32 bits, UINT32 nbits);
WINPR_API void BitStream_Flush(wBitStream* bs);
WINPR_API void BitStream_Prefetch(wBitStream* bs);
WINPR_API void BitStream_Fetch(wBitStream* bs);
WINPR_API void BitStream_Shift(wBitStream* bs, UINT32 nbits);
WINPR_API void BitDump(const BYTE* buffer, UINT32 length, UINT32 flags);
WINPR_API wBitStream* BitStream_New();
WINPR_API void BitStream_Free(wBitStream* bs);
#ifdef __cplusplus
}
#endif
#endif /* WINPR_UTILS_BITSTREAM_H */

View File

@@ -27,6 +27,7 @@
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/stream.h>
@@ -596,65 +597,8 @@ WINPR_API int PubSub_OnEvent(wPubSub* pubSub, const char* EventName, void* conte
WINPR_API wPubSub* PubSub_New(BOOL synchronized);
WINPR_API void PubSub_Free(wPubSub* pubSub);
/* BitStream */
struct _wBitStream
{
BYTE* buffer;
BYTE* pointer;
DWORD position;
DWORD length;
DWORD capacity;
UINT32 offset;
UINT32 accumulator;
};
typedef struct _wBitStream wBitStream;
#define BitStream_Attach(_bs, _buffer, _capacity) { \
_bs->position = 0; \
_bs->buffer = _buffer; \
_bs->offset = 0; \
_bs->accumulator = 0; \
_bs->pointer = _bs->buffer; \
_bs->capacity = _capacity; \
_bs->length = _bs->capacity; \
}
#define BitStream_Write_Bits(_bs, _bits, _nbits) { \
_bs->accumulator |= (_bits << _bs->offset); \
_bs->position += _nbits; \
_bs->offset += _nbits; \
if (_bs->offset >= 32) { \
*(_bs->pointer + 0) = (_bs->accumulator >> 0); \
*(_bs->pointer + 1) = (_bs->accumulator >> 8); \
*(_bs->pointer + 2) = (_bs->accumulator >> 16); \
*(_bs->pointer + 3) = (_bs->accumulator >> 24); \
_bs->offset = _bs->offset - 32; \
_bs->accumulator = _bits >> (_nbits - _bs->offset); \
_bs->pointer += 4; \
} \
}
#define BitStream_Flush(_bs) { \
if ((_bs->pointer - _bs->buffer) > 0) \
*(_bs->pointer + 0) = (_bs->accumulator >> 0); \
if ((_bs->pointer - _bs->buffer) > 1) \
*(_bs->pointer + 1) = (_bs->accumulator >> 8); \
if ((_bs->pointer - _bs->buffer) > 2) \
*(_bs->pointer + 2) = (_bs->accumulator >> 16); \
if ((_bs->pointer - _bs->buffer) > 3) \
*(_bs->pointer + 3) = (_bs->accumulator >> 24); \
}
#define BITDUMP_MSB_FIRST 0x00000001
#define BITDUMP_STDERR 0x00000002
WINPR_API void BitDump(BYTE* buffer, UINT32 length, UINT32 flags);
WINPR_API wBitStream* BitStream_New();
WINPR_API void BitStream_Free(wBitStream* bs);
#ifdef __cplusplus
}
#endif
#endif /* WINPR_COLLECTIONS_H */

View File

@@ -21,7 +21,7 @@
#include "config.h"
#endif
#include <winpr/collections.h>
#include <winpr/bitstream.h>
const char* BYTE_BIT_STRINGS_LSB[256] =
{
@@ -159,7 +159,7 @@ const char* BYTE_BIT_STRINGS_MSB[256] =
"00111111", "10111111", "01111111", "11111111"
};
void BitDump(BYTE* buffer, UINT32 length, UINT32 flags)
void BitDump(const BYTE* buffer, UINT32 length, UINT32 flags)
{
DWORD i;
int nbits;
@@ -174,12 +174,126 @@ void BitDump(BYTE* buffer, UINT32 length, UINT32 flags)
nbits = (length - i) > 8 ? 8 : (length - i);
if ((i % 64) == 0)
printf("\n");
printf("%.*s ", nbits, str);
}
printf("\n");
}
void BitStream_Attach(wBitStream* bs, BYTE* buffer, UINT32 capacity)
{
bs->position = 0;
bs->buffer = buffer;
bs->offset = 0;
bs->accumulator = 0;
bs->pointer = bs->buffer;
bs->capacity = capacity;
bs->length = bs->capacity * 8;
}
void BitStream_Flush(wBitStream* bs)
{
if ((bs->pointer - bs->buffer) < (bs->capacity + 0))
*(bs->pointer + 0) = (bs->accumulator >> 24);
if ((bs->pointer - bs->buffer) < (bs->capacity + 1))
*(bs->pointer + 1) = (bs->accumulator >> 16);
if ((bs->pointer - bs->buffer) < (bs->capacity + 2))
*(bs->pointer + 2) = (bs->accumulator >> 8);
if ((bs->pointer - bs->buffer) < (bs->capacity + 3))
*(bs->pointer + 3) = (bs->accumulator >> 0);
}
void BitStream_Prefetch(wBitStream* bs)
{
(bs->prefetch) = 0;
if ((bs->pointer - bs->buffer) < (bs->capacity + 4))
(bs->prefetch) |= (*(bs->pointer + 4) << 24);
if ((bs->pointer - bs->buffer) < (bs->capacity + 5))
(bs->prefetch) |= (*(bs->pointer + 5) << 16);
if ((bs->pointer - bs->buffer) < (bs->capacity + 6))
(bs->prefetch) |= (*(bs->pointer + 6) << 8);
if ((bs->pointer - bs->buffer) < (bs->capacity + 7))
(bs->prefetch) |= (*(bs->pointer + 7) << 0);
}
void BitStream_Fetch(wBitStream* bs)
{
(bs->accumulator) = 0;
if ((bs->pointer - bs->buffer) < (bs->capacity + 0))
(bs->accumulator) |= (*(bs->pointer + 0) << 24);
if ((bs->pointer - bs->buffer) < (bs->capacity + 1))
(bs->accumulator) |= (*(bs->pointer + 1) << 16);
if ((bs->pointer - bs->buffer) < (bs->capacity + 2))
(bs->accumulator) |= (*(bs->pointer + 2) << 8);
if ((bs->pointer - bs->buffer) < (bs->capacity + 3))
(bs->accumulator) |= (*(bs->pointer + 3) << 0);
BitStream_Prefetch(bs);
}
void BitStream_Write_Bits(wBitStream* bs, UINT32 bits, UINT32 nbits)
{
bs->position += nbits;
bs->offset += nbits;
if (bs->offset < 32)
{
bs->accumulator |= (bits << (32 - bs->offset));
}
else
{
bs->offset -= 32;
bs->mask = ((1 << (nbits - bs->offset)) - 1);
bs->accumulator |= ((bits >> bs->offset) & bs->mask);
BitStream_Flush(bs);
bs->accumulator = 0;
bs->pointer += 4;
if (bs->offset)
{
bs->mask = ((1 << bs->offset) - 1);
bs->accumulator |= ((bits & bs->mask) << (32 - bs->offset));
}
}
}
void BitStream_Shift(wBitStream* bs, UINT32 nbits)
{
bs->accumulator <<= nbits;
bs->position += nbits;
bs->offset += nbits;
if (bs->offset < 32)
{
bs->mask = ((1 << nbits) - 1);
bs->accumulator |= ((bs->prefetch >> (32 - nbits)) & bs->mask);
bs->prefetch <<= nbits;
}
else
{
bs->mask = ((1 << nbits) - 1);
bs->accumulator |= ((bs->prefetch >> (32 - nbits)) & bs->mask);
bs->prefetch <<= nbits;
bs->offset -= 32;
bs->pointer += 4;
BitStream_Prefetch(bs);
if (bs->offset)
{
bs->mask = ((1 << bs->offset) - 1);
bs->accumulator |= ((bs->prefetch >> (32 - bs->offset)) & bs->mask);
bs->prefetch <<= bs->offset;
}
}
}
wBitStream* BitStream_New()
{
wBitStream* bs = NULL;

View File

@@ -2,7 +2,7 @@
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/stream.h>
#include <winpr/collections.h>
#include <winpr/bitstream.h>
void BitStrGen()
{