/////////////////////////////////////////////////////////////////////////////////////////
// Project: SP Data Formatting Library 1.5
//
// File: RealEFormatter.h
//
// Developer(s): Sergei Pavlovsky
// sergei_vp@hotmail.com
// Copyright (c) 2004-2005
//
// Description:
//
// 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.
/////////////////////////////////////////////////////////////////////////////////////////
#if !defined(__SP_REALEFORMATTER_H__INCLUDED__)
#define __SP_REALEFORMATTER_H__INCLUDED__
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "RealFormatter.h"
namespace SP
{
/////////////////////////////////////////////////////////////////////////////////////////
// Formatting objects
/////////////////////////////////////////////////////////////////////////////////////////
class CExponentSegment;
class CRealELiteralSegment;
class CRealEDigitalPattern;
class CRealELiteralPattern;
class CRealEFormatter;
/////////////////////////////////////////////////////////////////////////////////////////
// CRealECompositionCtx class
/////////////////////////////////////////////////////////////////////////////////////////
class CRealECompositionCtx : public CRealCompositionCtx
{
// Declarations
public:
friend class CRealEFormatter;
// Construction
public:
CRealECompositionCtx(const CRealEFormatter* pcFormatter, DWORD fOptions);
// Operations
public:
void ChangePattern(const CRealEDigitalPattern* pcPattern);
void ChangePattern(const CRealELiteralPattern* pcPattern);
// Accessors & mutators
public:
UINT_PTR GetMinExponentDigits() const
{
return m_cMinExponentDigits;
}
UINT_PTR GetMaxExponentDigits() const
{
return m_cMaxExponentDigits;
}
protected:
const CRealEFormatter* GetFormatter() const;
// Data members
private:
UINT_PTR m_cMinExponentDigits;
UINT_PTR m_cMaxExponentDigits;
};
/////////////////////////////////////////////////////////////////////////////////////////
// CRealDataCtx class
/////////////////////////////////////////////////////////////////////////////////////////
class CRealEDataCtx : public CRealDataCtx
{
// Declarations
public:
friend class CRealEFormatter;
// Construction
public:
CRealEDataCtx(const CRealEFormatter* pcFormatter);
// Accessors & mutators
protected:
const CRealEFormatter* GetFormatter() const;
public:
SIZE_T GetDigitalPatterns(const CRealEDigitalPattern** prgPatters) const;
const CRealEDigitalPattern& GetPatternForExponent(char nSign) const;
};
/////////////////////////////////////////////////////////////////////////////////////////
// CExponentSegment class
/////////////////////////////////////////////////////////////////////////////////////////
class CExponentSegment : public CNumericDigitalRTLSegment
{
// Types
public:
typedef CRealECompositionCtx TCompCtx;
typedef CNumericGenerationCtx TGenrCtx;
typedef CNumericTranslationCtx TTranCtx;
typedef CRealEDataCtx TDataCtx;
// Types
private:
typedef CCtxAutoSwitch<TCompCtx, CExponentSegment> CCompCtxAutoSwitch;
typedef CCtxAutoSwitch<TGenrCtx, CExponentSegment> CGenrCtxAutoSwitch;
typedef CCtxAutoSwitch<TTranCtx, CExponentSegment> CTranCtxAutoSwitch;
typedef CCtxAutoSwitch<TDataCtx, CExponentSegment> CDataCtxAutoSwitch;
// Constants
protected:
enum EnumTokens
{
TN_EXPONENT = _T('e')
};
// Constants: Formatting & scanning
protected:
enum StandardValues
{
SV_PLUS = _T('+'),
SV_MINUS = _T('-'),
SV_EXPONENT = _T('e')
};
// Construction & destruction
public:
CExponentSegment()
{
}
CExponentSegment(const CExponentSegment& src)
: CNumericDigitalRTLSegment(src)
{
}
~CExponentSegment()
{
}
// Operators
public:
CExponentSegment& operator=(const CExponentSegment& right)
{
CNumericDigitalRTLSegment::operator=(right);
return *this;
}
// Operations: Common
public:
UINT _GetGeneralOperationErrorReason(EnumGeneralOperations enOp) const;
// Helpers: Expression
protected:
SIZE_T ComposeTraitsToken(CNumericCompositionCtx& ctx,
CNumericFormatTraits::TokensEnum enToken,
LPTSTR& lpBuf, SIZE_T& cchBuf) const;
void GenerateToken(const CToken& token, TCHAR& chToken,
LPCTSTR* ppcSymbol, SIZE_T* pcchSymbol) const throw();
CToken TranslateToken(TCHAR chEntry, LPCTSTR lpcChar, SIZE_T cchChar) const;
// Operations: Expression
public:
bool IsReservedSymbol(LPCTSTR lpcSymbol, SIZE_T cchSymbol) const
{
ATLASSERT( !::IsBadReadPtr(lpcSymbol, cchSymbol * sizeof(TCHAR)) );
ATLASSERT( cchSymbol > 0 );
return *lpcSymbol == TN_EXPONENT ||
CNumericDigitalRTLSegment::IsReservedSymbol(lpcSymbol, cchSymbol);
}
SIZE_T ComposeExpression(CCompositionCtx& ctx, LPTSTR& lpBuf, SIZE_T& cchBuf) const;
// Operations: Formatting & scanning
public:
SIZE_T Format(CNumericDataCtx& ctx, LPCTSTR lpcValue, SIZE_T cchValue,
LPTSTR& lpBuffer, SIZE_T& cchBuffer) const;
SIZE_T Scan(CNumericDataCtx& ctx, LPCTSTR lpcText, SIZE_T cchText,
LPTSTR& lpBuffer, SIZE_T& cchBuffer) const;
};
/////////////////////////////////////////////////////////////////////////////////////////
// CRealELiteralSegment class
/////////////////////////////////////////////////////////////////////////////////////////
class CRealELiteralSegment : public CRealLiteralSegment
{
// Types
public:
typedef CRealECompositionCtx TCompCtx;
typedef CNumericGenerationCtx TGenrCtx;
typedef CNumericTranslationCtx TTranCtx;
typedef CRealEDataCtx TDataCtx;
// Types
private:
typedef CCtxAutoSwitch<TCompCtx, CRealELiteralSegment> CCompCtxAutoSwitch;
typedef CCtxAutoSwitch<TGenrCtx, CRealELiteralSegment> CGenrCtxAutoSwitch;
typedef CCtxAutoSwitch<TTranCtx, CRealELiteralSegment> CTranCtxAutoSwitch;
typedef CCtxAutoSwitch<TDataCtx, CRealELiteralSegment> CDataCtxAutoSwitch;
// Constants
protected:
enum EnumTokens
{
TN_EXPONENT = _T('e')
};
// Construction & destruction
public:
CRealELiteralSegment()
{
}
CRealELiteralSegment(const CRealELiteralSegment& src)
: CRealLiteralSegment(src)
{
}
~CRealELiteralSegment()
{
}
// Operators
public:
CRealELiteralSegment& operator=(const CRealELiteralSegment& right)
{
CRealLiteralSegment::operator=(right);
return *this;
}
// Operations: Common
public:
UINT _GetGeneralOperationErrorReason(EnumGeneralOperations enOp) const;
// Helpers: Expression
protected:
SIZE_T ComposeTraitsToken(CNumericCompositionCtx& ctx,
CNumericFormatTraits::TokensEnum enToken,
LPTSTR& lpBuf, SIZE_T& cchBuf) const
{
if ( enToken == CNumericFormatTraits::TK_GROUPSEPARATOR )
return CFormatter::WriteTokenFwd(ctx, lpBuf, cchBuf, TN_THOUSANDSSEPARATOR);
else
return CRealLiteralSegment::ComposeTraitsToken(ctx, enToken, lpBuf, cchBuf);
}
void GenerateToken(const CToken& token, TCHAR& chToken, LPCTSTR* ppcSymbol,
SIZE_T* pcchSymbol) const throw()
{
ATLASSERT( !::IsBadWritePtr(ppcSymbol, sizeof(LPCTSTR)) );
ATLASSERT( !::IsBadWritePtr(pcchSymbol, sizeof(SIZE_T)) );
ATLASSERT( *ppcSymbol == &chToken && *pcchSymbol == 1 && chToken == _T('\x0') );
if ( token.GetAction() == CToken::CA_SETEXPONENT )
chToken = TN_EXPONENT;
else
CRealLiteralSegment::GenerateToken(token, chToken, ppcSymbol, pcchSymbol);
}
CToken TranslateToken(TCHAR chToken, LPCTSTR lpcChar, SIZE_T cchChar) const
{
ATLASSERT( !::IsBadReadPtr(lpcChar, cchChar * sizeof(TCHAR)) );
// Define command and its parameter
if ( chToken == TN_EXPONENT )
return CToken(CToken::CA_SETEXPONENT, CToken::CC_NON);
else
return CRealLiteralSegment::TranslateToken(chToken, lpcChar, cchChar);
}
// Operations: Expression
public:
bool IsReservedSymbol(LPCTSTR lpcSymbol, SIZE_T cchSymbol) const
{
ATLASSERT( !::IsBadReadPtr(lpcSymbol, cchSymbol * sizeof(TCHAR)) );
ATLASSERT( cchSymbol > 0 );
return *lpcSymbol == TN_EXPONENT ||
CRealLiteralSegment::IsReservedSymbol(lpcSymbol, cchSymbol);
}
};
/////////////////////////////////////////////////////////////////////////////////////////
// CRealEDigitalPattern class
/////////////////////////////////////////////////////////////////////////////////////////
class CRealEDigitalPattern : public CRealDigitalPattern
{
// Types
public:
typedef CRealECompositionCtx TCompCtx;
typedef CNumericGenerationCtx TGenrCtx;
typedef CNumericTranslationCtx TTranCtx;
typedef CRealEDataCtx TDataCtx;
// Types
private:
typedef CCtxAutoSwitch<TCompCtx, CRealEDigitalPattern> CCompCtxAutoSwitch;
typedef CCtxAutoSwitch<TGenrCtx, CRealEDigitalPattern> CGenrCtxAutoSwitch;
typedef CCtxAutoSwitch<TTranCtx, CRealEDigitalPattern> CTranCtxAutoSwitch;
typedef CCtxAutoSwitch<TDataCtx, CRealEDigitalPattern> CDataCtxAutoSwitch;
// Constants: Common
public:
enum EnumSegments
{
SG_EXPONENT = 0x00000500
};
private:
static const UINT ms_aDigitalSegmentIDs[];
// Constants: Expression
protected:
enum EnumTokens
{
TN_EXPONENT = _T('e')
};
// Constants: Formatting & scanning
protected:
enum StandardValues
{
SV_EXPONENT = _T('e')
};
// Types: Expression
protected:
struct EExpression : FExpression
{
LPCTSTR lpcExponent;
SIZE_T cchExponent;
UINT_PTR cExponentBaseLevel;
};
// Types: Formatting & scanning
protected:
struct EValueParts : FValueParts
{
char nExponentSign;
LPCTSTR lpcExponent;
SIZE_T cchExponent;
};
// Construction & destruction
protected:
CRealEDigitalPattern()
{
}
CRealEDigitalPattern(const CRealEDigitalPattern& src)
: CRealDigitalPattern(src),
m_segExponent(src.m_segExponent)
{
}
// Operators
protected:
CRealEDigitalPattern& operator=(const CRealEDigitalPattern& right)
{
CRealDigitalPattern::operator=(right);
// Segment class handles self assignment
m_segExponent = right.m_segExponent;
return *this;
}
#ifdef _DEBUG
// Debug
public:
// CTString DumpContent() const;
#endif // _DEBUG
// Helpers: Common
protected:
SIZE_T GetDigitalSegments(const CNumericDigitalSegment** prgSegments) const;
SIZE_T GetDigitalSegments(CNumericDigitalSegment** prgSegments);
// Helpers: Expression
protected:
void ParseEExpression(CExpressionCtx& ctx, LPCTSTR lpcSrc, SIZE_T cchSrc,
EExpression* pExpr) const;
void ParseExpression(CExpressionCtx& ctx, LPCTSTR lpcSrc, SIZE_T cchSrc,
SExpression* prgSExpressions) const;
// Operations: Expression
public:
void Clear()
{
m_segExponent.Clear();
CRealDigitalPattern::Clear();
}
bool IsEmpty() const
{
return m_segExponent.IsEmpty() && CRealDigitalPattern::IsEmpty();
}
SIZE_T ComposeExpression(CCompositionCtx& ctx, LPTSTR& lpBuf, SIZE_T& cchBuf) const
{
ATLASSERT( !::IsBadWritePtr(lpBuf, cchBuf * sizeof(TCHAR)) );
CCompCtxAutoSwitch ctxSwitch(ctx, this);
return Compose(ctxSwitch.GetCtx(), lpBuf, cchBuf);
}
// Helpers: Formatting & scanning
protected:
void ParseStdTextEValue(CRealEDataCtx& ctx, LPCTSTR lpcValue, SIZE_T cchValue,
EValueParts* pVP) const;
SIZE_T FormatExponent(CRealEDataCtx& ctx, char nSigh,
LPCTSTR lpcValue, SIZE_T cchValue,
LPTSTR& lpBuffer, SIZE_T& cchBuffer) const;
void ParseTextEValue(CRealEDataCtx& ctx, LPCTSTR lpcText, SIZE_T cchText,
EValueParts* pVP) const;
SIZE_T ScanExponent(CRealEDataCtx& ctx, LPCTSTR lpcText, SIZE_T cchText,
LPTSTR& lpBuffer, SIZE_T& cchBuffer) const;
SIZE_T _Format(CRealEDataCtx& ctx, LPCTSTR lpcValue, SIZE_T cchValue,
LPTSTR lpBuffer, SIZE_T cchBuffer) const;
SIZE_T _Scan(CRealEDataCtx& ctx, LPCTSTR lpcText, SIZE_T cchText,
LPTSTR lpBuffer, SIZE_T cchBuffer) const;
// Data members
protected:
CExponentSegment m_segExponent;
};
/////////////////////////////////////////////////////////////////////////////////////////
// CRealELiteralPattern class
/////////////////////////////////////////////////////////////////////////////////////////
class CRealELiteralPattern : public CRealLiteralPattern
{
// Types
public:
typedef CRealECompositionCtx TCompCtx;
typedef CNumericGenerationCtx TGenrCtx;
typedef CNumericTranslationCtx TTranCtx;
typedef CRealEDataCtx TDataCtx;
typedef CRealELiteralSegment TSegment;
// Types
private:
typedef CCtxAutoSwitch<TCompCtx, CRealEDigitalPattern> CCompCtxAutoSwitch;
typedef CCtxAutoSwitch<TGenrCtx, CRealEDigitalPattern> CGenrCtxAutoSwitch;
typedef CCtxAutoSwitch<TTranCtx, CRealEDigitalPattern> CTranCtxAutoSwitch;
typedef CCtxAutoSwitch<TDataCtx, CRealEDigitalPattern> CDataCtxAutoSwitch;
// Construction & destruction
protected:
CRealELiteralPattern()
{
}
CRealELiteralPattern(const CRealELiteralPattern& src)
: CRealLiteralPattern(src)
{
}
// Operators
protected:
CRealELiteralPattern& operator=(const CRealELiteralPattern& right)
{
return static_cast<CRealELiteralPattern&>(CRealLiteralPattern::operator=(right));
}
};
/////////////////////////////////////////////////////////////////////////////////////////
// CRealENullPattern class template
/////////////////////////////////////////////////////////////////////////////////////////
class CRealENullPattern : public CRealELiteralPattern
{
// Types
private:
typedef CCtxAutoSwitch<TCompCtx, CRealENullPattern> CCompCtxAutoSwitch;
typedef CCtxAutoSwitch<TGenrCtx, CRealENullPattern> CGenrCtxAutoSwitch;
typedef CCtxAutoSwitch<TTranCtx, CRealENullPattern> CTranCtxAutoSwitch;
typedef CCtxAutoSwitch<TDataCtx, CRealENullPattern> CDataCtxAutoSwitch;
// Construction & destruction
public:
CRealENullPattern()
{
}
CRealENullPattern(const CRealENullPattern& src)
: CRealELiteralPattern(src)
{
}
~CRealENullPattern()
{
}
// Operators
public:
CRealENullPattern& operator=(const CRealENullPattern& right)
{
CRealELiteralPattern::operator=(right);
return *this;
}
// Helpers: Common
protected:
const CNumericLiteralSegment& GetSegment() const
{
return m_segment;
}
CNumericLiteralSegment& GetSegment()
{
return m_segment;
}
// Operarions: Common
public:
CNumericFormatTraits::TokensEnum GetDefultTraitsToken() const
{
return CNumericFormatTraits::TK_NULL;
}
UINT _GetGeneralOperationErrorReason(EnumGeneralOperations enOp) const;
// Operations: Formatting & scanning
public:
SIZE_T Format(CDataCtx& ctx, const void* lpcValue,
LPTSTR lpBuffer, SIZE_T cchBuffer) const;
bool Matches(CDataCtx& ctx, LPCTSTR lpcText, SIZE_T cchText) const;
bool Scan(CDataCtx& ctx, LPCTSTR lpcText, SIZE_T cchText,
void* lpValue, bool* pbNotNull) const;
// Data members
private:
TSegment m_segment;
};
/////////////////////////////////////////////////////////////////////////////////////////
// CRealEFormatter class
/////////////////////////////////////////////////////////////////////////////////////////
class CRealEFormatter : public CRealFormatter
{
// Declarations
public:
friend class CRealEDataCtx;
// Types
public:
typedef CRealECompositionCtx TCompCtx;
typedef CNumericGenerationCtx TGenrCtx;
typedef CNumericTranslationCtx TTranCtx;
typedef CRealEDataCtx TDataCtx;
typedef CRealEDigitalPattern TDigitalPattern;
typedef CRealELiteralPattern TLiteralPattern;
typedef CRealENullPattern TNullPattern;
// Construction & destruction
protected:
CRealEFormatter(LCID lcid, WORD fTraits = TRAIT_NUMBER)
: CRealFormatter(lcid, fTraits)
{
}
// Helpers: Common
protected:
virtual SIZE_T GetDigitalPatterns(
const CRealEDigitalPattern** prgPatters) const = 0;
// Operations: Expression
public:
SIZE_T ComposeMaskExpression(LPTSTR lpBuffer, SIZE_T cchBuffer,
DWORD fOptions = 0) const // throw (ELogError)
{
return _ComposeMask(CRealECompositionCtx(this, fOptions), lpBuffer, cchBuffer);
}
// Helpers: Formatting & scanning
protected:
virtual const CRealEDigitalPattern& GetPatternForExponent(char nSign) const = 0;
// Operations: Formatting & scanning
public:
SIZE_T Format(const void* lpcValue, LPTSTR lpBuffer, SIZE_T cchBuffer) const;
bool Matches(LPCTSTR lpcText, SIZE_T cchText) const;
bool Scan(LPCTSTR lpcText, SIZE_T cchText, void* lpValue, bool* pbNotNull) const;
};
/////////////////////////////////////////////////////////////////////////////////////////
// CRealCompositionCtx class implementation
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
// Construction
inline CRealECompositionCtx::CRealECompositionCtx(const CRealEFormatter* pcFormatter,
DWORD fOptions)
: CRealCompositionCtx(pcFormatter, fOptions),
m_cMinExponentDigits(0),
m_cMaxExponentDigits(CNumericSegment::DC_UNLIMITED)
{
}
/////////////////////////////////////////////////////////////////////////////////////////
// Operations
inline void CRealECompositionCtx::ChangePattern(const CRealEDigitalPattern* pcPattern)
{
CRealCompositionCtx::ChangePattern(pcPattern);
if ( pcPattern )
{
const CNumericFormatTraits& ft =
static_cast<const CNumericFormatTraits&>(GetFormatter()->GetFormatTraits());
m_cMinExponentDigits = ft.GetExponentDigitsNumber();
m_cMaxExponentDigits = pcPattern->IsZero()
? m_cMinExponentDigits
: CNumericSegment::DC_UNLIMITED;
}
}
inline void CRealECompositionCtx::ChangePattern(const CRealELiteralPattern* pcPattern)
{
CRealCompositionCtx::ChangePattern(pcPattern);
}
/////////////////////////////////////////////////////////////////////////////////////////
// Accessors & mutators
inline const CRealEFormatter* CRealECompositionCtx::GetFormatter() const
{
return static_cast<const CRealEFormatter*>(CRealCompositionCtx::GetFormatter());
}
/////////////////////////////////////////////////////////////////////////////////////////
// CRealEDataCtx class
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
// Construction
inline CRealEDataCtx::CRealEDataCtx(const CRealEFormatter* pcFormatter)
: CRealDataCtx(pcFormatter)
{
}
/////////////////////////////////////////////////////////////////////////////////////////
// Accessors & mutators
inline const CRealEFormatter* CRealEDataCtx::GetFormatter() const
{
return static_cast<const CRealEFormatter*>(CRealDataCtx::GetFormatter());
}
inline SIZE_T CRealEDataCtx::GetDigitalPatterns(const CRealEDigitalPattern** prgPatters) const
{
return GetFormatter()->GetDigitalPatterns(prgPatters);
}
inline const CRealEDigitalPattern& CRealEDataCtx::GetPatternForExponent(char nSign) const
{
return GetFormatter()->GetPatternForExponent(nSign);
}
}; // namespace SP
#endif // !defined(__SP_REALEFORMATTER_H__INCLUDED__)