typedef void (*pfn_outputchar)( void *, int );
typedef void (*pfn_outputtext)( void *, const char *, size_t );
typedef struct _output_target
{
pfn_outputchar pFnOutputChar;
pfn_outputtext pFnOutputText;
void * pData;
void putChar( int ch )
{
pFnOutputChar( pData, ch );
}
void putText( const char * pText, size_t len )
{
pFnOutputText( pData, pText, len );
}
}st_output_target;
typedef void (*pfn_output_value)( st_output_target * pTarget, const void*, const char * );
template <typename T>
struct tout
{
static void _output(st_output_target * pTarget)
{
pTarget->putText( __FUNCTION__, strlen( __FUNCTION__ ) );
}
};
struct st_output_unknown_converter
{
st_output_unknown_converter( const char * pszText )
{
_T = pszText;
_Len = strlen( pszText );
}
const char * _T;
size_t _Len;
};
template <typename T>
void t_output_value( st_output_target * pTarget, const void * pV, const char * pStyle )
{
st_output_unknown_converter ocvt( *(T*) pV );
pTarget->putText( ocvt._T, ocvt._Len );
}
template <>
void t_output_value<int>( st_output_target * pTarget, const void * pV, const char * pStyle )
{
char szIntText[20];
size_t len = sprintf( szIntText, "%d", *(int*)pV );
pTarget->putText( szIntText, len );
}
template <>
void t_output_value<char *>( st_output_target * pTarget, const void * pV, const char * pStyle )
{
char * p = *(char**)pV;
size_t len = strlen( p );
pTarget->putText( p, len );
}
template <>
void t_output_value<const char *>( st_output_target * pTarget, const void * pV, const char * pStyle )
{
size_t len = strlen( *(char**)pV );
pTarget->putText( *(char**)pV, len );
}
template <>
void t_output_value<char[]>( st_output_target * pTarget, const void * pV, const char * pStyle )
{
size_t len = strlen( *(char**)pV );
pTarget->putText( *(char**)pV, len );
}
typedef struct _output_param
{
pfn_output_value pFn;
const void * pValue;
}st_output_param;
// compile-time type transformation
template<typename T>
struct ptr_decay {
typedef T type;
};
template<typename T>
struct ptr_decay<T[]> {
typedef T* type;
};
template<typename T, std::size_t N>
struct ptr_decay<T[N]> {
typedef T* type;
};
template <typename T1>
void t_output( st_output_target * pTarget, const char * pszText, const T1 & v1 )
{
const int paramCount = 1;
typename ptr_decay<T1>::type _v1 = (typename ptr_decay<T1>::type)v1;
st_output_param params[paramCount] = {
{ t_output_value<typename ptr_decay<T1>::type>, &_v1 },
};
const char * p = pszText;
int iState = 0;
const char * pParamBegin = NULL;
const char * pParamStyleBegin = NULL;
const char * pTextBegin = pszText;
while( *p )
{
if( iState == 0 )
{
if( *p == '{' )
{
size_t textLen = (size_t)(p-pTextBegin);
if( textLen > 0 )
{
pTarget->putText( pTextBegin, textLen );
}
pParamBegin = p;
pParamStyleBegin = NULL;
iState = 1;
}
}
else if( iState == 1 )
{
if( *p == ':' )
{
pParamStyleBegin = p;
}
else if( *p == '}' )
{
char szIndex[20];
char szStyle[20];
int iIndexLen = pParamStyleBegin == NULL ? (int)(p-pParamBegin)-1 : (int)(pParamStyleBegin - pParamBegin) - 1;
int iStyleLen = pParamStyleBegin == NULL ? 0 : (int)(p-pParamStyleBegin)-1;
if( iIndexLen > 0 && iIndexLen <= 3 )
{
strncpy( szIndex, pParamBegin + 1, iIndexLen );
szIndex[iIndexLen] = 0;
if( iStyleLen > 0 && iStyleLen <= 10 )
{
strncpy(szStyle, pParamStyleBegin, iStyleLen);
szStyle[iStyleLen] = 0;
}
else
szStyle[0] = 0;
int iParamIndex = atoi( szIndex );
if( iParamIndex >= 0 &&
iParamIndex < paramCount )
{
params[iParamIndex].pFn( pTarget, params[iParamIndex].pValue, szStyle );
}
}
iState = 0;
pTextBegin = p + 1;
}
}
++p;
}
size_t textLen = (size_t)( p - pTextBegin );
if( textLen > 0 )
{
pTarget->putText( pTextBegin, textLen );
}
}
void _output_char( void *, int ch )
{
putchar( ch );
}
void _output_text( void *, const char * pszText, size_t len )
{
for( int i = 0;i < (int)len; ++i )
{
putchar( pszText[i] );
}
}
int main(int argc, char* argv[])
{
st_output_target ot =
{
_output_char,
_output_text,
NULL
};
char * astr = "abc";
t_output(&ot, "test {0}\n", "abc");