Files
Sun1602/Utility/SafeStringBufferControl.h
2022-10-26 12:25:11 +08:00

391 lines
12 KiB
C++

#pragma once
#include <boost/static_assert.hpp>
/*---------------------------------------------------------------------------------------
@Author : Waverix
@Date : 2007-04-28
@Reference
- Utility/Documents/"Safe String Buffer Control Classes.doc"
@Remark
- 시작 동기는 네트워크 버퍼에서 문자열 스트림 처리가 안정적이지 못해서...
- stl::string도 여기에는 취약한 면을 보인다.
- (2007/04/19)
- 종류는 작업용 버퍼, 읽기전용 문자열 처리, 읽고쓰기가능 문자열 처리
@Prototypes
-> class cSTRING_BUFFER;
-> class cSTRING_REF
// 등록된 버퍼를 읽고 쓰기용으로 사용할 경우
-> class cSTRING_REF_RW : public cSTRING_REF
// 내부 포함 버퍼를 읽고 쓰기용으로 사용할 경우
-> template<typename BYTE _SZ> class cSTRING_REF_RW_WITH_BUFFER : public cSTRING_REF_RW
//---------------------------------------------------------------------------------------
*/
namespace util
{
//////////////////////////////////////////////////////////////////////////
#pragma pack(push, 1)
// 패킷에서 안전하게 사용하기 위한 컨테이너
template<typename WORD _SZ>
class cSTRING_BUFFER
{
friend class cSTRING_REF;
public:
static const DWORD SZ_BUFFER_LENGTH = _SZ*sizeof(TCHAR);;
static const DWORD SZ_STRING_LENGTH_WITH_NULL = _SZ;
BOOST_STATIC_ASSERT( SZ_STRING_LENGTH_WITH_NULL >= 1 );
static const DWORD SZ_STRING_LENGTH = SZ_STRING_LENGTH_WITH_NULL-1;
public: cSTRING_BUFFER() { BUFINFO.pBUFFER[0] = _T('\0'); }
cSTRING_BUFFER( const TCHAR* ptsSrc ) { CopyFrom( ptsSrc ); }
template<typename _TYPE_SB>
explicit cSTRING_BUFFER( const _TYPE_SB& rSrc ) { CopyFrom( rSrc ); }
~cSTRING_BUFFER() {}
// <METHODs>
public: inline TCHAR* GetBUFFER() { return BUFINFO.pBUFFER; }
inline operator TCHAR*() { return BUFINFO.pBUFFER; }
inline operator TCHAR*() const { return const_cast<TCHAR*>(BUFINFO.pBUFFER); }
inline WORD GetBUFFER_LENGTH() { return sizeof(BUFINFO.pBUFFER); }
inline INT GetSTRING_LENGTH() { return GetCalcStringLength(); }
public: inline const TCHAR* GetBUFFER() const { return BUFINFO.pBUFFER; }
inline operator const TCHAR*() const { return BUFINFO.pBUFFER; }
inline WORD GetBUFFER_LENGTH() const { return sizeof(BUFINFO.pBUFFER); }
inline INT GetSTRING_LENGTH() const { return GetCalcStringLength(); }
inline BOOL IsReadOnly() { return FALSE; }
protected: INT GetCalcStringLength()
{
DWORD dwLen = 0;
TCHAR* pOffset = BUFINFO.pBUFFER;
while( (_SZ > dwLen) && (_T('\0') != *pOffset++) )
++dwLen;
return dwLen;
}
public: INT CopyFrom( const TCHAR* ptsSrc )
{
DWORD dwLen = 0;
const TCHAR* pSrc = ptsSrc;
for( TCHAR* pTarget = BUFINFO.pBUFFER ; (dwLen<_SZ) && (_T('\0') != *pSrc) ; ++dwLen )
*pTarget++ = *pSrc++;
if( _SZ == dwLen )
{
BUFINFO.pBUFFER[SZ_STRING_LENGTH] = _T('\0');
return dwLen-1;
}
// 버퍼 나머지 부분 클리어
if( dwLen ) memset( &(BUFINFO.pBUFFER[dwLen]), 0, ((DWORD)_SZ-dwLen) );
else BUFINFO.pBUFFER[0] = _T('\0');
return dwLen;
}
BOOL MakeSafeString()
{
TCHAR& rChr = BUFINFO.pBUFFER[SZ_STRING_LENGTH];
if( rChr != _T('\0') )
rChr = _T('\0');
return TRUE;
}
// <METHODs>
protected: inline TCHAR* BUFFER_HDR() { return BUFINFO.pBUFFER; }
inline WORD BUFFER_LENGTH() const { return sizeof(BUFINFO.pBUFFER); }
// <FIELDs>
private: struct
{
TCHAR pBUFFER[_SZ];
} BUFINFO;
};
#pragma pack(pop)
//////////////////////////////////////////////////////////////////////////
// 기본은 등록된 버퍼의 문자열을 읽기전용으로 처리하는 클래스
class cSTRING_REF
{
// <TYPE DEFINITIONs>
protected: struct eMODE
{
static const DWORD NONE = 0x00; // 초기화 값
static const DWORD CALCULATED = 0x01;
};
// <CONSTRUCTORs>
public: cSTRING_REF() { BUFINFO.wBUFFER_LENGTH = 0; BUFINFO.wSTRING_LENGTH = 0; BUFINFO.pBUFFER = NULL; BUFINFO.eMODEs = eMODE::NONE; }
~cSTRING_REF() {}
cSTRING_REF( const TCHAR* pStrBuffer, const WORD wBufferLen )
{ BUFINFO.wBUFFER_LENGTH = wBufferLen; BUFINFO.wSTRING_LENGTH = 0; BUFINFO.pBUFFER = (TCHAR*)pStrBuffer; BUFINFO.eMODEs = eMODE::NONE; }
cSTRING_REF( const cSTRING_REF* pSOURCE )
{ memcpy( &BUFINFO, &(pSOURCE->BUFINFO), sizeof(BUFINFO) ); }
template<typename _cSTRING_BUFFER_TYPE_>
cSTRING_REF( const _cSTRING_BUFFER_TYPE_& rBUF_SRC )
{ BUFINFO.wBUFFER_LENGTH = rBUF_SRC.BUFFER_LENGTH();
BUFINFO.wSTRING_LENGTH = 0;
BUFINFO.pBUFFER = (TCHAR*)rBUF_SRC.BUFINFO.pBUFFER;
BUFINFO.eMODEs = eMODE::NONE; }
protected: cSTRING_REF( WORD wBufferLen, WORD wStrLen, TCHAR* pBuffer, DWORD eMode )
{
BUFINFO.wBUFFER_LENGTH = wBufferLen;
BUFINFO.wSTRING_LENGTH = wStrLen;
BUFINFO.pBUFFER = (TCHAR*)pBuffer;
BUFINFO.eMODEs = eMode; }
// <METHODs>
public: virtual BOOL IsReadOnly() { return TRUE; }
public: inline TCHAR* GetBUFFER() { return BUFINFO.pBUFFER; }
inline WORD GetBUFFER_LENGTH() { return BUFINFO.wBUFFER_LENGTH; }
inline INT GetSTRING_LENGTH() { return GetCalcStringLength(); }
protected: inline TCHAR* BUFFER_HDR() { return BUFINFO.pBUFFER; }
inline WORD BUFFER_LENGTH() { return BUFINFO.wBUFFER_LENGTH; }
inline WORD& STRING_LENGTH() { return BUFINFO.wSTRING_LENGTH; }
// <returns><INT>
// -1 : 읽을 수 없는 버퍼
// n : 안전하게 읽을 수 있는 문자열 길이, 이것은 null-terminate 되지 않은 문자열일 경우 버퍼크기
protected: virtual INT GetCalcStringLength()
{
if( BUFINFO.pBUFFER && IsBadReadPtr( BUFINFO.pBUFFER, sizeof(BYTE) ) )
{
BUFINFO.eMODEs = eMODE::NONE;
return -1;
}
if( eMODE::CALCULATED == BUFINFO.eMODEs )
return (INT)BUFINFO.wSTRING_LENGTH;
DWORD dwBufferLen = (DWORD)BUFINFO.wBUFFER_LENGTH;
DWORD dwLen = 0;
TCHAR* pOffset = BUFINFO.pBUFFER;
while( (dwBufferLen > dwLen) && (_T('\0') != *pOffset++) )
++dwLen;
BUFINFO.wSTRING_LENGTH = (WORD)dwLen;
BUFINFO.eMODEs = eMODE::CALCULATED;
return (INT)dwLen;
}
public: virtual BOOL MakeSafeString() { return FALSE; }
// <comment> this의 문자열이 출력버퍼보다 커도 tempBuffer.BUFFER_SIZE-1 만큼 복사하고 NULL처리를 수행한다.
// <returns> 복사한 문자열 길이, -1이면 복사 실패
public: template<typename _cSTRING_BUFFER_TYPE_>
INT CopyTo( _cSTRING_BUFFER_TYPE_& OUT rOUTBUF )
{
if( rOUTBUF.IsReadOnly() )
return -1;
INT iRet = GetCalcStringLength();
if( iRet < 0 ) return iRet;
if( BUFINFO.pBUFFER == rOUTBUF.BUFINFO.pBUFFER )
{
rOUTBUF.BUFINFO.wBUFFER_LENGTH = BUFINFO.wBUFFER_LENGTH;
rOUTBUF.BUFINFO.wSTRING_LENGTH = BUFINFO.wSTRING_LENGTH;
rOUTBUF.BUFINFO.eMODEs = BUFINFO.eMODEs;
return iRet;
}
iRet = sizeof(TCHAR)*iRet;
WORD wTmpBufferLen = rOUTBUF.BUFFER_LENGTH();
BOOL bLessThanTHIS = (BOOL) !(iRet < (INT)wTmpBufferLen);
if( bLessThanTHIS )
{
memcpy( rOUTBUF.BUFFER_HDR(), BUFINFO.pBUFFER, wTmpBufferLen );
rOUTBUF.BUFFER_HDR()[wTmpBufferLen-1] = _T('\0');
rOUTBUF.STRING_LENGTH() = wTmpBufferLen-1;
rOUTBUF.BUFINFO.eMODEs = eMODE::CALCULATED;
return (INT)rOUTBUF.STRING_LENGTH();
}
if( iRet )
{
memcpy( rOUTBUF.BUFFER_HDR(), BUFINFO.pBUFFER, iRet );
rOUTBUF.BUFFER_HDR()[iRet] = _T('\0');
rOUTBUF.STRING_LENGTH() = (WORD)(iRet);
rOUTBUF.BUFINFO.eMODEs = eMODE::CALCULATED;
return (INT)rOUTBUF.STRING_LENGTH();
}
rOUTBUF.BUFFER_HDR()[0] = _T('\0');
rOUTBUF.STRING_LENGTH() = 0;
rOUTBUF.BUFINFO.eMODEs = eMODE::CALCULATED;
return 0;
}
template<typename _cSTRING_BUFFER_TYPE_>
INT CopyFrom( _cSTRING_BUFFER_TYPE_& IN rINBUF )
{
if( IsReadOnly() )
return -1;
INT iRet = rINBUF.GetCalcStringLength();
if( iRet < 0 ) return iRet;
if( BUFINFO.pBUFFER == rINBUF.BUFINFO.pBUFFER )
{
BUFINFO.wBUFFER_LENGTH = rINBUF.BUFINFO.wBUFFER_LENGTH;
BUFINFO.wSTRING_LENGTH = rINBUF.BUFINFO.wSTRING_LENGTH;
BUFINFO.eMODEs = rINBUF.BUFINFO.eMODEs;
return iRet;
}
iRet = sizeof(TCHAR)*iRet;
WORD wTmpBufferLen = BUFFER_LENGTH();
BOOL bLessThanTHIS = (BOOL) !(iRet < (INT)wTmpBufferLen);
if( bLessThanTHIS )
{
memcpy( BUFFER_HDR(), rINBUF.BUFFER_HDR(), wTmpBufferLen );
BUFFER_HDR()[wTmpBufferLen-1] = _T('\0');
STRING_LENGTH() = wTmpBufferLen-1;
BUFINFO.eMODEs = eMODE::CALCULATED;
return (INT)STRING_LENGTH();
}
if( iRet )
{
memcpy( BUFFER_HDR(), rINBUF.BUFFER_HDR(), iRet );
BUFFER_HDR()[iRet] = _T('\0');
STRING_LENGTH() = (WORD)(iRet);
BUFINFO.eMODEs = eMODE::CALCULATED;
return (INT)STRING_LENGTH();
}
BUFFER_HDR()[0] = _T('\0');
STRING_LENGTH() = 0;
BUFINFO.eMODEs = eMODE::CALCULATED;
return 0;
}
INT CopyFromString( const TCHAR* pSrcString )
{
if( IsReadOnly() )
return -1;
DWORD dwBufferLen = (DWORD)BUFFER_LENGTH();
DWORD dwLen = 0;
TCHAR* pSrcOffset = (TCHAR*)pSrcString;
TCHAR* pOffset = BUFFER_HDR();
while( (dwBufferLen > dwLen) && (_T('\0') != *pSrcOffset) )
{
*pOffset = *pSrcOffset;
++dwLen;
++pOffset;
++pSrcOffset;
}
if( dwBufferLen > dwLen )
{
BUFFER_HDR()[dwBufferLen-1] = _T('\0');
BUFFER_HDR()[dwLen] = _T('\0');
}
// if( dwBufferLen == dwLen ) no null-terminate
STRING_LENGTH() = (WORD)dwLen;
BUFINFO.eMODEs = eMODE::CALCULATED;
return (INT)STRING_LENGTH();
}
// <FIELDs>
protected: struct
{
WORD wBUFFER_LENGTH;
WORD wSTRING_LENGTH;
DWORD eMODEs;
TCHAR* pBUFFER;
} BUFINFO;
};
//////////////////////////////////////////////////////////////////////////
// 등록된 버퍼를 읽고 쓰기용으로 사용할 경우
class cSTRING_REF_RW : public cSTRING_REF
{
friend class cSTRING_REF;
// <CONSTRUCTORs>
public: cSTRING_REF_RW() : cSTRING_REF() {}
~cSTRING_REF_RW() {}
cSTRING_REF_RW( const TCHAR* pStrBuffer, const WORD wBufferLen ) : cSTRING_REF( pStrBuffer, wBufferLen ) {}
cSTRING_REF_RW( const cSTRING_REF* pSOURCE ) : cSTRING_REF( pSOURCE ) {}
template<typename _cSTRING_BUFFER_TYPE_>
cSTRING_REF_RW( const _cSTRING_BUFFER_TYPE_& rBUF_SRC ) : cSTRING_REF( rBUF_SRC ) {}
protected: cSTRING_REF_RW( WORD wBufferLen, WORD wStrLen, TCHAR* pBuffer, DWORD eMode ) : cSTRING_REF( wBufferLen, wStrLen, pBuffer, eMode ) {}
// <METHODs>
public: virtual BOOL IsReadOnly() { return FALSE; }
// <returns><INT>
// -1 : 읽을 수 없는 버퍼
// n : 안전하게 읽을 수 있는 문자열 길이, 이것은 null-terminate 되지 않은 문자열일 경우 (버퍼크기-1)
protected: virtual INT GetCalcStringLength()
{
if( (!BUFINFO.pBUFFER)
|| (0 == BUFINFO.wBUFFER_LENGTH)
|| IsBadReadPtr( BUFINFO.pBUFFER, sizeof(BYTE) ) )
return -1;
if( eMODE::CALCULATED == BUFINFO.eMODEs )
return (INT)BUFINFO.wSTRING_LENGTH;
DWORD dwBufferLen = (DWORD)BUFINFO.wBUFFER_LENGTH;
DWORD dwLen = 0;
TCHAR* pOffset = BUFINFO.pBUFFER;
while( (dwBufferLen > dwLen) && (_T('\0') != *pOffset++) )
++dwLen;
if( dwBufferLen != dwLen )
BUFINFO.wSTRING_LENGTH = (WORD)dwLen;
else
BUFINFO.wSTRING_LENGTH = (WORD)( dwLen ? dwLen-1 : 0 );
BUFINFO.eMODEs = eMODE::CALCULATED;
return (INT)(BUFINFO.wSTRING_LENGTH);
}
public: virtual BOOL MakeSafeString()
{
INT iRet = GetCalcStringLength();
if( iRet < 0 )
return FALSE;
if( IsBadWritePtr( BUFINFO.pBUFFER, BUFINFO.wBUFFER_LENGTH ) )
return FALSE;
BUFINFO.pBUFFER[BUFINFO.wSTRING_LENGTH] = _T('\0');
BUFINFO.pBUFFER[BUFINFO.wBUFFER_LENGTH-1] = _T('\0');
return TRUE;
}
};
//////////////////////////////////////////////////////////////////////////
// 내부 포함 버퍼로 읽고 쓰기용으로 사용할 경우
template<typename WORD _SZ>
class cSTRING_REF_RW_WITH_BUFFER : public cSTRING_REF_RW
{
// <CONSTRUCTORs>
public: cSTRING_REF_RW_WITH_BUFFER() : cSTRING_REF_RW( BUFFER_BLOCK.GetBUFFER(), (WORD)BUFFER_BLOCK.GetBUFFER_LENGTH() ) {}
protected: cSTRING_BUFFER<_SZ> BUFFER_BLOCK;
};
}; //namespace