| | |
|
组别 | 士兵 |
级别 | 忠义校尉 |
好贴 | 1 |
功绩 | 7 |
帖子 | 274 |
编号 | 17912 |
注册 | 2004-9-18 |
| |
| | |
|
|
|
// Msg_Codec.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <crtdbg.h>
#ifndef BYTE
typedef unsigned char BYTE;
#endif
static const int DICT_LEN = 0x100;
static const int ACTUAL_LEN = 0x9DE3A;
class CLS11
{
// Operations
public:
//---------------------------------------------------------------------------
// Inputs: pDict -- Pointer to the dictionary.
// pSrc -- Pointer to source data buffer.
// pDest -- Pointer to destination data buffer.
// nLenActual -- Length of valid source data.
// nLenSrc -- Length of source data buffer.
// nLenDest -- Length of destination data buffer.
// bCompress -- true if LZ compression needs to be taken.
// Returns: The length of encoded data.
// Summary: Call this method to encode specified data with LS11.
//--------------------------------------------------------------------------
int Encode( BYTE *pDict, const BYTE *pSrc, BYTE *pDest, int nLenActual, int nLenSrc, int nLenDest, bool bCompress = false );
//--------------------------------------------------------------------------
// Inputs: pDict -- Pointer to the dictionary.
// pSrc -- Pointer to source data buffer.
// pDest -- Pointer to destination data buffer.
// nLenSrc -- Length of source data buffer.
// nLenDest -- Length of destination data buffer.
// nLenActual -- Length of original data.
// Returns: The length of decoded data.
// Summary: Call this method to decode LS11-encoded data. This procedure is
// based on the code written by Maxwell & van.
//--------------------------------------------------------------------------
int Decode( BYTE *pDict, const BYTE *pSrc, BYTE *pDest, int nLenActual, int nLenSrc, int nLenDest );
// Properties
protected:
int m_srcpos;
int m_destpos;
int m_bitpos;
BYTE *m_pDest;
const BYTE *m_pSrc;
// Implementations
protected:
void SetCode( unsigned int code );
unsigned int GetCode( );
void ReorderDict( BYTE const *pDictSrc, BYTE *pDictDest, int nLenDict );
} ;
int CLS11::Encode( BYTE *pDict, const BYTE *pSrc, BYTE *pDest, int nLenActual, int nLenSrc, int nLenDest, bool bCompress )
{
int off, len, lenmax, offmax;
BYTE *pNewDict = new BYTE[DICT_LEN];
m_pDest = pDest;
m_pSrc = pSrc;
m_srcpos = 0;
m_destpos = 0;
m_bitpos = 0;
_ASSERT( nLenActual <= nLenSrc && pNewDict );
memset( m_pDest, 0, nLenDest );
ReorderDict( pDict, pNewDict, DICT_LEN );
// If no compress needs to be taken, use dictionary only.
if( !bCompress )
{
while( m_srcpos < nLenActual && m_destpos < nLenDest )
{
SetCode( pNewDict[m_pSrc[m_srcpos++]] );
}
}
else
{
while( m_srcpos < nLenActual && m_destpos < nLenDest )
{
// Scan whole text
for( off = 1, lenmax = 0, offmax = 1; off <= m_srcpos; off++ )
{
for( len = 0; len + m_srcpos < nLenSrc && m_pSrc[m_srcpos - off + len] == m_pSrc[m_srcpos + len]; len++ );
if( len > lenmax )
{
lenmax = len;
offmax = off;
}
}
// Replace the duplicated string with two number: offmax + 256 and lenmax - 3
if( lenmax >= 3 )
{
SetCode( offmax + 256 );
SetCode( lenmax - 3 );
m_srcpos += lenmax;
}
else
{
SetCode( pNewDict[m_pSrc[m_srcpos++]] );
}
}
}
while( m_bitpos )
{
m_pDest[m_destpos] <<= 1;
m_bitpos++;
if( m_bitpos > 7 )
{
m_bitpos = 0;
m_destpos++;
break;
}
}
delete [] pNewDict;
return m_destpos;
}
int CLS11:ecode( BYTE *pDict, const BYTE *pSrc, BYTE *pDest, int nLenActual, int nLenSrc, int nLenDest )
{
unsigned int code, off, len;
m_pSrc = pSrc;
m_destpos = 0;
m_srcpos = 0;
m_bitpos = 7;
_ASSERT( nLenActual <= nLenDest );
while( m_srcpos < nLenSrc && m_destpos < nLenActual )
{
code = GetCode( );
if( code < 256 )
{
pDest[m_destpos++] = pDict[code];
}
else
{
off = code - 256;
len = GetCode( ) + 3;
for( unsigned int i = 0; i < len && m_destpos < nLenDest; i++ )
{
pDest[m_destpos] = pDest[m_destpos - off];
m_destpos++;
}
}
}
// Padding
while( m_destpos < nLenActual )
{
pDest[m_destpos++] = pDict[0];
}
return m_destpos;
}
void CLS11::SetCode( unsigned int code )
{
unsigned int temp, code1, code2;
int len, i;
temp = code;
len = 0;
code1 = 0;
// How many valid bits are contained in variable code
while( temp > 1)
{
temp >>= 1;
code1 = (code1 << 1) | 0x01;
len++;
}
if( (code1 << 1) <= code )
{
len++;
code1 = code & (~1);
}
else
code1--;
code2 = code - code1;
// Output bits of code1
for( i = len - 1; i >= 0; i-- )
{
m_pDest[m_destpos] = (m_pDest[m_destpos] << 1) | (code1 >> i);
m_bitpos++;
if( m_bitpos > 7)
{
m_bitpos = 0;
m_destpos++;
}
}
// Output bits of code2
for( i = len - 1; i >= 0; i-- )
{
m_pDest[m_destpos] = (m_pDest[m_destpos] << 1) | (code2 >> i);
m_bitpos++;
if( m_bitpos > 7)
{
m_bitpos = 0;
m_destpos++;
}
}
}
unsigned int CLS11::GetCode( )
{
unsigned int code1 = 0, code2 = 0;
int len = 0, bit;
do
{
bit = (m_pSrc[m_srcpos] >> m_bitpos) & 0x01;
code1 = (code1 << 1) | bit;
len++;
m_bitpos--;
if( m_bitpos < 0 )
{
m_bitpos = 7;
m_srcpos++;
}
} while( bit );
for( int i = 0; i < len; i++ )
{
bit = (m_pSrc[m_srcpos] >> m_bitpos) & 0x01;
code2 = (code2 << 1) | bit;
m_bitpos--;
if( m_bitpos < 0 )
{
m_bitpos = 7;
m_srcpos++;
}
}
return (code1 + code2);
}
void CLS11::ReorderDict( const BYTE *pDictSrc, BYTE *pDictDest, int nLenDict )
{
for( int i = 0; i < nLenDict; i++ )
{
for( int j = 0; j < nLenDict; j++ )
{
if( pDictSrc[j] == i )
{
pDictDest = j;
break;
}
}
}
}
// Big-endian to Little-endian or reverse
int Convert( int x )
{
int ret = 0;
BYTE *p = (BYTE *)(&x);
ret = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
return ret;
}
void TestEncode()
{
CLS11 ls11;
BYTE *pDict, *pSrc, *pDest;
int l1, l2, off, zero = 0;// Big-endian values
pDict = new BYTE[DICT_LEN];
FILE *fin = fopen("C:/code/m_msg_dec.s9", "rb");
FILE *fout = fopen("C:/code/m_msg_enc1.s9", "wb");
FILE *fout2 = fopen("C:/code/m_msg_enc2.s9", "wb");
_ASSERT( fin && fout && fout2 && pDict );
fread( pDict, 0x10, 1, fin );
fwrite( pDict, 0x10, 1, fout );
fwrite( pDict, 0x10, 1, fout2 );
fread( pDict, 0x100, 1, fin );
fwrite( pDict, 0x100, 1, fout );
fwrite( pDict, 0x100, 1, fout2 );
fread( &l1, 4, 1, fin );
pSrc = new BYTE[Convert(l1)];
fread( &l2, 4, 1, fin );
pDest = new BYTE[Convert(l2)];
fread( &off, 4, 1, fin );
_ASSERT( pSrc && pDest );
fseek( fin, Convert(off), SEEK_SET );
fseek( fout, Convert(off), SEEK_SET );
fread( pSrc, Convert(l1), 1, fin );
int nLen = ls11.Encode( pDict, pSrc, pDest, ACTUAL_LEN, Convert(l1), Convert(l2), false );
fwrite( pDest, nLen, 1, fout );
fseek( fout, 0x110, SEEK_SET );
l1 = Convert( nLen );
fwrite( &l1, 4, 1, fout );
fwrite( &l2, 4, 1, fout );
fwrite( &off, 4, 1, fout );
fwrite( &zero, 4, 1, fout );
nLen = ls11.Encode( pDict, pSrc, pDest, ACTUAL_LEN, Convert(l2), Convert(l2), true );
fseek( fout2, Convert(off), SEEK_SET );
fwrite( pDest, nLen, 1, fout2 );
fseek( fout2, 0x110, SEEK_SET );
l1 = Convert( nLen );
fwrite( &l1, 4, 1, fout2 );
fwrite( &l2, 4, 1, fout2 );
fwrite( &off, 4, 1, fout2 );
fwrite( &zero, 4, 1, fout2 );
fclose( fin );
fclose( fout );
fclose( fout2 );
delete [] pDict;
delete [] pSrc;
delete [] pDest;
}
void TestDecode()
{
CLS11 ls11;
BYTE *pDict, *pSrc, *pDest;
int l1, l2, off, zero = 0;
pDict = new BYTE[DICT_LEN];
FILE *fin = fopen("I:/San9pk/m_msg.s9", "rb");
FILE *fout = fopen("C:/code/m_msg_dec.s9", "wb");
_ASSERT( fin && fout && pDict );
fread( pDict, 0x10, 1, fin );
fwrite( pDict, 0x10, 1, fout );
fread( pDict, 0x100, 1, fin );
fwrite( pDict, 0x100, 1, fout );
fread( &l1, 4, 1, fin );
l1 = Convert( l1 );
pSrc = new BYTE[l1];
fread( &l2, 4, 1, fin );
l2 = Convert( l2 );
pDest = new BYTE[12];
fread( &off, 4, 1, fin );
off = Convert( off );
_ASSERT( pSrc && pDest );
fseek( fin, off, SEEK_SET );
fseek( fout, off, SEEK_SET );
fread( pSrc, 0x47EEF, 1, fin );
int nLen = ls11.Decode( pDict, pSrc, pDest, ACTUAL_LEN, l1, l2 );
fwrite( pDest, nLen, 1, fout );
fseek( fout, 0x110, SEEK_SET );
l1 = l2 = Convert( nLen );
fwrite( &l1, 4, 1, fout );
fwrite( &l2, 4, 1, fout );
off = Convert( off );
fwrite( &off, 4, 1, fout );
fwrite( &zero, 4, 1, fout );
fclose( fin );
fclose( fout );
delete [] pDict;
delete [] pSrc;
delete [] pDest;
}
int _tmain(int argc, _TCHAR* argv[])
{
//TestDecode();
TestEncode();
return 0;
}
|
|
|