#ifndef __pack_h__
#define __pack_h__
#include <string>
static bool is_big_endian()
{
static unsigned short test_number = 0x1234;
static bool fIsBigEndian = ( *( (char*)(&test_number) ) == 0x12 );
return fIsBigEndian;
}
static int limit_max(int input, int max)
{
return ( input > max && max > 0 )?max:input;
}
template<class T>
T exchange_value(T val)
{
T retval = val;
if( !is_big_endian() )
{
int ibytes = (int) sizeof( T );
for( int i = 0; i < ibytes; i++ )
{
*( ( (char*)&retval )+i ) = *( ( (char*)&val ) + ibytes - 1 - i );
}
}
return retval;
}
class TPack
{
public:
typedef enum{PACK=0, UNPACK} PACK_CODE;
static int MAX_PACK_SIZE;
public:
TPack( PACK_CODE code, int cbmax = MAX_PACK_SIZE )
{
m_ctlCode = code;
m_pdata = 0;
m_cbdata = 0;
m_offset = 0;
allocbuffer( cbmax );
}
virtual ~TPack()
{
destroy();
}
private:
void destroy()
{
free( m_pdata );
m_pdata = 0;
m_cbdata = 0;
m_offset = 0;
}
protected:
TPack& operator<<(__int8 ch1)
{
pack_data( &ch1, 1 );
return *this;
}
TPack& operator<<(__int16 ch2)
{
__int16 val = exchange_value<__int16>(ch2);
pack_data( (char*)&val, 2 );
return *this;
}
TPack& operator<<(__int32 ch4)
{
__int32 val = exchange_value<__int32>(ch4);
pack_data( (char*)&val, 4 );
return *this;
}
TPack& operator<<(__int64 ch8)
{
__int64 val = exchange_value<__int64>(ch8);
pack_data( (char*)&val, 8 );
return *this;
}
TPack& operator<<(bool b)
{
__int8 ch1 = b?1:0;
(*this)<<ch1;
return *this;
}
TPack& operator<<(float f)
{
__int32 ch4 = 0;
memcpy(&ch4, &f, 4);
(*this)<<ch4;
return *this;
}
TPack& operator<<(double dbl)
{
__int64 ch8 = 0;
memcpy(&ch8, &dbl, 8);
(*this)<<ch8;
return *this;
}
TPack& operator>>(__int8& ch1)
{
unpack_data( &ch1, 1 );
return *this;
}
TPack& operator>>(__int16& ch2)
{
__int16 val = 0;
unpack_data( (char*)&val, 2 );
ch2 = exchange_value<__int16>(val);
return *this;
}
TPack& operator>>(__int32& ch4)
{
__int32 val = 0;
unpack_data( (char*)&val, 4 );
ch4 = exchange_value<__int32>(val);
return *this;
}
TPack& operator>>(__int64& ch8)
{
__int64 val = 0;
unpack_data( (char*)&val, 8 );
ch8 = exchange_value<__int64>(val);
return *this;
}
TPack& operator>>(bool& b)
{
__int8 ch1 = 0;
(*this)>>ch1;
b = ( ch1 != 0 );
return *this;
}
TPack& operator>>(float& f)
{
__int32 ch4 = 0;
(*this)>>ch4;
memcpy(&f, &ch4, 4);
return *this;
}
TPack& operator>>(double& dbl)
{
__int64 ch8 = 0;
(*this)>>ch8;
memcpy(&dbl, &ch8, 8);
return *this;
}
void pack_data( const char* pdata, int cbdata )
{
if( m_ctlCode == UNPACK || pdata == 0 || cbdata <=0 || ( m_cbdata+cbdata ) > m_cbmax )
throw "pack data error!";
memcpy( m_pdata+m_offset, pdata, cbdata );
m_offset += cbdata;
m_cbdata = m_offset;
}
void unpack_data( char* pdata, int cbdata )
{
if( m_ctlCode == PACK || pdata == 0 || cbdata <=0 || ( m_offset+cbdata ) > m_cbmax )
throw "unpack data error!";
memcpy( pdata, m_pdata+m_offset, cbdata );
m_offset += cbdata;
}
bool ispacking()
{
return ( m_ctlCode == PACK ) ;
}
public:
bool allocbuffer( int size )
{
if( m_pdata == 0 )
{
m_pdata = (char*) malloc ( size );
m_cbmax = size;
}
else if( size > m_cbmax )
{
m_pdata = (char*) realloc ( m_pdata, size );
m_cbmax = size;
}
return ( m_pdata != 0 );
}
bool copydata( char* pdata, int cbdata )
{
if( allocbuffer( cbdata ) && ( pdata != 0 ) )
{
return serial( pdata, cbdata );
}
return false;
}
template<class T>
bool serial( T& val )
{
try
{
if( ispacking() )
{
(*this)<<val;
}
else
{
(*this)>>val;
}
return true;
}
catch(char* strerr)
{
printf( "%s\n", strerr );
}
return false;
}
bool serial( char* pdata, int size )
{
try
{
if( ispacking() )
{
pack_data( pdata, size );
}
else
{
unpack_data( pdata, size );
}
return true;
}
catch(char* strerr)
{
printf( "%s\n", strerr );
}
return false;
}
bool serial( std::string& str, int maxsize = -1 )
{
try
{
if( ispacking() )
{
int ilen = limit_max( str.length(), maxsize );
(*this) << ilen;
if( ilen > 0 )
serial( (char*)str.c_str(), ilen );
}
else
{
int ilen = 0;
str.empty();
(*this) >> ilen;
ilen = limit_max( ilen, maxsize );
if( ilen > 0 )
{
char* pdata = (char*) malloc ( ilen+1 );
*( pdata + ilen ) = 0;
serial( pdata, ilen );
str.assign(pdata, ilen+1);
}
}
return true;
}
catch(char* strerr)
{
printf( "%s\n", strerr );
}
return false;
}
bool serial( std::wstring& str, int maxsize = -1 )
{
try
{
if( ispacking() )
{
int ilen = limit_max( str.length(), maxsize ) * 2;
(*this) << ilen;
if( ilen > 0 )
serial( (char*)str.c_str(), ilen );
}
else
{
int ilen = 0;
str.empty();
(*this) >> ilen;
ilen = limit_max( ilen, maxsize );
if( ilen > 0 )
{
char* pdata = (char*) malloc ( ilen+2 );
*( pdata + ilen ) = 0;
*( pdata + ilen + 1 ) = 0;
serial( pdata, ilen );
str.assign((wchar_t*)pdata, ilen/2);
}
}
return true;
}
catch(char* strerr)
{
printf( "%s\n", strerr );
}
return false;
}
void reset(PACK_CODE code)
{
m_ctlCode = code;
m_offset = 0;
}
char* data() const
{
return m_pdata;
}
char* wdata()
{
return m_pdata;
}
int size() const
{
return m_cbdata;
}
private:
PACK_CODE m_ctlCode;
char* m_pdata;
int m_cbdata;
int m_offset;
int m_cbmax;
};
int TPack::MAX_PACK_SIZE = 102400;
#endif
pack serial
最新推荐文章于 2024-07-18 00:15:00 发布