/////////////////////////////////////////////////////////////////////////////////////////
// Project: SP Data Formatting Library 1.5
//
// File: BinarySignedIntegerFormatter.h
//
// Developer(s): Sergei Pavlovsky
// sergei_vp@hotmail.com
// Copyright (c) 2004-2005
//
// Description: Classes used for a handling of binary signed integer data.
//
// Platforms: Win32, ATL
//
// This code may be used in compiled form in any way you desire. This file may be
// redistributed unmodified by any means PROVIDING it is not sold for profit without
// the authors written consent, and providing that this notice and the authors name
// is included. If the source code in this file is used in any commercial application
// then acknowledgement must be made to the author of this file (in whatever form
// you wish).
//
// This file is provided "as is" with no expressed or implied warranty. The author
// accepts no liability for any damage/loss of business that this product may cause.
/////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "IntegerFormatter.h"
namespace SP
{
/////////////////////////////////////////////////////////////////////////////////////////
// CSignedInt8Base class
/////////////////////////////////////////////////////////////////////////////////////////
class CSignedInt8Base
{
// Constants
public:
enum
{
MAX_CONVBUFFER = 5
};
// Types
public:
typedef char TCore;
// Utilities: Formatting & scanning
public:
static SIZE_T _RawFormat(char value, LPTSTR lpszBuffer);
static bool _RawScan(LPCTSTR lpcszNumber, char* pValue);
};
/////////////////////////////////////////////////////////////////////////////////////////
// CSignedInt16Base class
/////////////////////////////////////////////////////////////////////////////////////////
class CSignedInt16Base
{
// Constants
public:
enum
{
MAX_CONVBUFFER = 7
};
// Types
public:
typedef short TCore;
// Utilities: Formatting & scanning
public:
static SIZE_T _RawFormat(short value, LPTSTR lpszBuffer);
static bool _RawScan(LPCTSTR lpcszNumber, short* pValue);
};
/////////////////////////////////////////////////////////////////////////////////////////
// CSignedInt32Base class
/////////////////////////////////////////////////////////////////////////////////////////
class CSignedInt32Base
{
// Constants
public:
enum
{
MAX_CONVBUFFER = 12
};
// Types
public:
typedef int TCore;
// Utilities: Formatting & scanning
public:
static SIZE_T _RawFormat(int value, LPTSTR lpszBuffer);
static bool _RawScan(LPCTSTR lpcszNumber, int* pValue);
};
/////////////////////////////////////////////////////////////////////////////////////////
// CSignedInt64Base class
/////////////////////////////////////////////////////////////////////////////////////////
class CSignedInt64Base
{
// Constants
public:
enum
{
MAX_CONVBUFFER = 21
};
// Types
public:
typedef __int64 TCore;
// Utilities: Formatting & scanning
public:
static SIZE_T _RawFormat(__int64 value, LPTSTR lpszBuffer);
static bool _RawScan(LPCTSTR lpcszNumber, __int64* pValue);
};
/////////////////////////////////////////////////////////////////////////////////////////
// CIEEERealDigitalPattern class template
/////////////////////////////////////////////////////////////////////////////////////////
template < class TCoreBase, char t_nSign, bool t_bZero >
class CBinarySignedIntegerDigitalPattern : public CIntegerDigitalPattern,
protected TCoreBase
{
// Types
public:
typedef typename TCoreBase::TCore TCore;
// Types
private:
typedef CCtxAutoSwitch<TCompCtx, CBinarySignedIntegerDigitalPattern>
CCompCtxAutoSwitch;
typedef CCtxAutoSwitch<TGenrCtx, CBinarySignedIntegerDigitalPattern>
CGenrCtxAutoSwitch;
typedef CCtxAutoSwitch<TTranCtx, CBinarySignedIntegerDigitalPattern>
CTranCtxAutoSwitch;
typedef CCtxAutoSwitch<TDataCtx, CBinarySignedIntegerDigitalPattern>
CDataCtxAutoSwitch;
// Construction & destruction
public:
CBinarySignedIntegerDigitalPattern()
{
}
CBinarySignedIntegerDigitalPattern(const CBinarySignedIntegerDigitalPattern& src)
: CIntegerDigitalPattern(src)
{
}
// Operators
public:
CBinarySignedIntegerDigitalPattern& operator=(
const CBinarySignedIntegerDigitalPattern& right)
{
CIntegerDigitalPattern::operator=(right);
return *this;
}
// Operations: Common
public:
char GetSign() const
{
return t_nSign;
}
bool IsZero() const
{
return t_bZero;
}
UINT _GetGeneralOperationErrorReason(EnumGeneralOperations enOp) const
{
// Depending on the template parameters optimizer will leave
// the only one of the following "if" statements.
if ( !t_bZero && t_nSign > 0 )
{
const UINT rgIDs[] =
{
EDF_COMPOSEPOSVALUEPATTERN,
EDF_GENERATEPOSVALUEPATTERN,
EDF_PARSEPOSVALUEPATTERN,
EDF_TRANSLATEPOSVALUEPATTERN,
0,
0,
0,
0
};
ATLASSERT( enOp < sizeof(rgIDs)/sizeof(UINT) );
return rgIDs[enOp];
}
if ( !t_bZero && t_nSign < 0 )
{
const UINT rgIDs[] =
{
EDF_COMPOSENEGVALUEPATTERN,
EDF_GENERATENEGVALUEPATTERN,
EDF_PARSENEGVALUEPATTERN,
EDF_TRANSLATENEGVALUEPATTERN,
0,
0,
0,
0
};
ATLASSERT( enOp < sizeof(rgIDs)/sizeof(UINT) );
return rgIDs[enOp];
}
if ( t_bZero )
{
const UINT rgIDs[] =
{
EDF_COMPOSEZEROPATTERN,
EDF_GENERATEZEROPATTERN,
EDF_PARSEZEROPATTERN,
EDF_TRANSLATEZEROPATTERN,
0,
0,
0,
0
};
ATLASSERT( enOp < sizeof(rgIDs)/sizeof(UINT) );
return rgIDs[enOp];
}
return 0;
}
// Helpers: Formatting & scanning
private:
SIZE_T _Format(TDataCtx& ctx, const TCore value, LPTSTR lpBuffer,
SIZE_T cchBuffer) const
{
ATLASSERT( !::IsBadWritePtr(lpBuffer, cchBuffer * sizeof(TCHAR)) );
// Perform standard formatting of the value
TCHAR szRaw[MAX_CONVBUFFER];
const SIZE_T cchRaw = _RawFormat(value, szRaw);
ATLASSERT( cchRaw < MAX_CONVBUFFER );
// Format the value according to the pattern
return CIntegerDigitalPattern::_Format(ctx, szRaw, cchRaw, lpBuffer, cchBuffer);
}
bool _Match(TDataCtx& ctx, LPCTSTR lpcText, SIZE_T cchText) const
{
ATLASSERT( !::IsBadReadPtr(lpcText, cchText * sizeof(TCHAR)) );
return CIntegerDigitalPattern::_Scan(ctx, lpcText, cchText, NULL, 0)
!= STATUS_FALSE;
}
bool _Scan(TDataCtx& ctx, LPCTSTR lpcText, SIZE_T cchText,
TCore* pValue, bool* pbNotNull) const
{
ATLASSERT( !::IsBadReadPtr(lpcText, cchText * sizeof(TCHAR)) );
ATLASSERT( !::IsBadWritePtr(pValue, sizeof(TCore)) );
ATLASSERT( !::IsBadWritePtr(pbNotNull, sizeof(bool)) );
bool bResult;
try
{
const SIZE_T cchRawBuf = cchText + 3;
CTempBuffer<TCHAR> bufRaw(cchRawBuf);
const SIZE_T cchRaw = CIntegerDigitalPattern::_Scan(ctx, lpcText, cchText,
bufRaw, cchRawBuf);
if ( cchRaw == STATUS_FALSE )
return false;
ATLASSERT( cchRaw < cchRawBuf );
bufRaw[cchRaw] = _T('\x0');
*pbNotNull = true;
bResult = _RawScan(bufRaw, pValue);
}
catch ( CAtlException& e )
{
throw EAtlLogError(e);
}
return bResult;
}
// Operations: Formatting & scanning
public:
SIZE_T Format(CDataCtx& ctx, const void* lpcValue,
LPTSTR lpBuffer, SIZE_T cchBuffer) const
{
ATLASSERT( !::IsBadReadPtr(lpcValue, sizeof(TCore)) );
ATLASSERT( !::IsBadWritePtr(lpBuffer, cchBuffer * sizeof(TCHAR)) );
CDataCtxAutoSwitch ctxSwitch(ctx, this);
const TCore* const pcValue = reinterpret_cast<const TCore*>(lpcValue);
return _Format(ctxSwitch.GetCtx(), *pcValue, lpBuffer, cchBuffer);
}
bool Matches(CDataCtx& ctx, LPCTSTR lpcText, SIZE_T cchText) const
{
ATLASSERT( !::IsBadReadPtr(lpcText, cchText * sizeof(TCHAR)) );
CDataCtxAutoSwitch ctxSwitch(ctx, this);
return _Match(ctxSwitch.GetCtx(), lpcText, cchText);
}
bool Scan(CDataCtx& ctx, LPCTSTR lpcText, SIZE_T cchText,
void* lpValue, bool* pbNotNull) const
{
ATLASSERT( !::IsBadReadPtr(lpcText, cchText * sizeof(TCHAR)) );
ATLASSERT( !::IsBadWritePtr(lpValue, sizeof(TCore)) );
ATLASSERT( !::IsBadWritePtr(pbNotNull, sizeof(bool)) );
CDataCtxAutoSwitch ctxSwitch(ctx, this);
TCore* const pValue = reinterpret_cast<TCore*>(lpValue);
return _Scan(ctxSwitch.GetCtx(), lpcText, cchText, pValue, pbNotNull);
}
};
/////////////////////////////////////////////////////////////////////////////////////////
// CBinarySignedIntegerFormatterBase class
/////////////////////////////////////////////////////////////////////////////////////////
class CBinarySignedIntegerFormatterBase
{
// Constants
protected:
enum EnumPatterns
{
PTM_PATTERN = 0x00FF,
PT_POSITIVENUMBER = 0x0000,
PT_NEGATIVENUMBER = 0x0001,
PT_ZERO = 0x0002,
PT_NULL = 0x0003,
PTC_DIGITAL = 0x0003,
PTC_TOTAL = 0x0004
};
};
/////////////////////////////////////////////////////////////////////////////////////////
// CBinarySignedIntegerFormatter class template
/////////////////////////////////////////////////////////////////////////////////////////
template < class TCoreBase >
class CBinarySignedIntegerFormatter : public CIntegerFormatter,
protected TCoreBase,
protected CBinarySignedIntegerFormatterBase
{
// Types
protected:
typedef typename TCoreBase::TCore TCore;
// Types
protected:
typedef CBinarySignedIntegerDigitalPattern<TCoreBase, 1, false >
CPositiveNumberPattern;
typedef CBinarySignedIntegerDigitalPattern<TCoreBase, -1, false >
CNegativeNumberPattern;
typedef CBinarySignedIntegerDigitalPattern<TCoreBase, 0, true >
CZeroPattern;
typedef CIntegerNullPattern
CNullPattern;
// Construction & destruction
protected:
CBinarySignedIntegerFormatter(LCID lcid, WORD fTraits = TRAIT_NUMBER)
: CIntegerFormatter(lcid, fTraits)
{
}
~CBinarySignedIntegerFormatter()
{
}
// Helpers: Common
protected:
SIZE_T GetPatterns(const CNumericPattern** prgPatterns) const
{
ATLASSERT( !prgPatterns ||
!::IsBadWritePtr(prgPatterns, PTC_TOTAL * sizeof(CNumericPattern*)) );
if ( prgPatterns )
{
prgPatterns[0] = &m_patternPosNumber;
prgPatterns[1] = &m_patternNegNumber;
prgPatterns[2] = &m_patternZero;
prgPatterns[3] = &m_patternNull;
}
return PTC_TOTAL;
}
SIZE_T GetPatterns(CNumericPattern** prgPatterns)
{
ATLASSERT( !prgPatterns ||
!::IsBadWritePtr(prgPatterns, PTC_TOTAL * sizeof(CNumericPattern*)) );
if ( prgPatterns )
{
prgPatterns[0] = &m_patternPosNumber;
prgPatterns[1] = &m_patternNegNumber;
prgPatterns[2] = &m_patternZero;
prgPatterns[3] = &m_patternNull;
}
return PTC_TOTAL;
}
// Helpers: Formatting and scanning
protected:
const CNumericPattern& GetAppropriatePattern(const void* lpcValue) const
{
ATLASSERT( !lpcValue || !::IsBadReadPtr(lpcValue, sizeof(float)) );
if ( lpcValue )
{
const TCore* pcVal = reinterpret_cast<const TCore*>(lpcValue);
if ( *pcVal > 0 )
return m_patternPosNumber;
else if ( *pcVal < 0 )
return m_patternNegNumber;
else
return m_patternZero;
}
else
{
return m_patternNull;
}
}
// Data members
protected:
CPositiveNumberPattern m_patternPosNumber;
CNegativeNumberPattern m_patternNegNumber;
CZeroPattern m_patternZero;
CNullPattern m_patternNull;
};
}; // namespace SP