handling of ptrs, first attempt

This commit is contained in:
Fischlurch 2011-12-31 01:30:07 +01:00
parent 35ed2dcf5c
commit c8f46f47c9
4 changed files with 145 additions and 85 deletions

View file

@ -69,10 +69,11 @@ namespace util {
return reinterpret_cast<boost::format&> (*buffer);
}
/** in case the formatting of a (primitive) value fails,
* we try to use a error indicator instead
*/
inline void
void
pushFailsafeReplacement (char* formatter, const char* errorMsg =NULL)
try {
string placeholder("<Error");
@ -87,6 +88,34 @@ namespace util {
ERROR_LOG_AND_IGNORE (progress, "Supplying placeholder for problematic format parameter")
/** Core function: let boost::format handle a value */
template<typename VAL>
void
doFormatParameter (char* formatter, VAL const& val)
try {
accessImpl(formatter) % val;
}
catch (boost::io::too_many_args& argErr)
{
WARN (progress, "Format: excess argument '%s' of type %s ignored."
, cStr(str(val))
, cStr(tyStr(val)));
}
catch (std::exception& failure)
{
WARN (progress, "Format: Parameter '%s' causes problems: %s"
, cStr(str(val))
, failure.what());
pushFailsafeReplacement (formatter, failure.what());
}
catch (...)
{
WARN (progress, "Format: Unexpected problems accepting format parameter '%s'", cStr(str(val)));
pushFailsafeReplacement (formatter);
}
inline void
suppressInsufficientArgumentErrors (char* formatter)
{
@ -128,75 +157,60 @@ namespace util {
*/
template<typename VAL>
void
_Fmt::pushParameter (VAL const& val)
try {
accessImpl(formatter_) % val;
}
catch (boost::io::too_many_args& argErr)
{
WARN (progress, "Format: excess argument '%s' of type %s ignored."
, cStr(str(val))
, cStr(tyStr(val)));
}
catch (std::exception& failure)
{
WARN (progress, "Format: Parameter '%s' causes problems: %s"
, cStr(str(val))
, failure.what());
pushFailsafeReplacement (formatter_, failure.what());
}
catch (...)
{
WARN (progress, "Format: Unexpected problems accepting format parameter '%s'", cStr(str(val)));
pushFailsafeReplacement (formatter_);
}
_Fmt::pushParameter (const VAL val)
{
doFormatParameter (formatter_, val);
}
template<typename VAL>
void
_Fmt::pushParameter (const VAL * const pVal)
_Fmt::pushParameter (const VAL * pVal)
{
if (pVal)
pushParameter (*pVal);
doFormatParameter (formatter_, *pVal);
else
pushParameter (string("<null>"));
doFormatParameter (formatter_, "<null>");
}
template<>
void
_Fmt::pushParameter (const char * const cString)
_Fmt::pushParameter (const char * cString)
{
pushParameter (cString);
doFormatParameter (formatter_, cString? cString : "" );
}
template<>
void
_Fmt::pushParameter (const void * address)
{
doFormatParameter (formatter_, address);
}
/* ===== explicitly supported =================== */
template void _Fmt::pushParameter(string const&);
template void _Fmt::pushParameter(char const&);
template void _Fmt::pushParameter(uchar const&);
template void _Fmt::pushParameter(int const&);
template void _Fmt::pushParameter(uint const&);
template void _Fmt::pushParameter(short const&);
template void _Fmt::pushParameter(ushort const&);
template void _Fmt::pushParameter(int64_t const&);
template void _Fmt::pushParameter(uint64_t const&);
template void _Fmt::pushParameter(float const&);
template void _Fmt::pushParameter(double const&);
template void _Fmt::pushParameter(void * const&);
template void _Fmt::pushParameter(const string);
template void _Fmt::pushParameter(const char);
template void _Fmt::pushParameter(const uchar);
template void _Fmt::pushParameter(const int);
template void _Fmt::pushParameter(const uint);
template void _Fmt::pushParameter(const short);
template void _Fmt::pushParameter(const ushort);
template void _Fmt::pushParameter(const int64_t);
template void _Fmt::pushParameter(const uint64_t);
template void _Fmt::pushParameter(const float);
template void _Fmt::pushParameter(const double);
template void _Fmt::pushParameter(const string * const);
template void _Fmt::pushParameter(const uchar * const);
template void _Fmt::pushParameter(const int * const);
template void _Fmt::pushParameter(const uint * const);
template void _Fmt::pushParameter(const short * const);
template void _Fmt::pushParameter(const ushort * const);
template void _Fmt::pushParameter(const int64_t * const);
template void _Fmt::pushParameter(const uint64_t * const);
template void _Fmt::pushParameter(const float * const);
template void _Fmt::pushParameter(const double * const);
template void _Fmt::pushParameter(const string * );
template void _Fmt::pushParameter(const uchar * );
template void _Fmt::pushParameter(const int * );
template void _Fmt::pushParameter(const uint * );
template void _Fmt::pushParameter(const short * );
template void _Fmt::pushParameter(const ushort * );
template void _Fmt::pushParameter(const int64_t *);
template void _Fmt::pushParameter(const uint64_t*);
template void _Fmt::pushParameter(const float * );
template void _Fmt::pushParameter(const double * );

View file

@ -99,10 +99,13 @@ namespace util {
struct Converter;
template<typename VAL>
void pushParameter (VAL const&);
void pushParameter (const VAL);
template<typename VAL>
void pushParameter (const VAL * const);
void pushParameter (const VAL *);
template<typename VAL>
void pushParameter (VAL *);
public:
@ -169,31 +172,44 @@ namespace util {
* As fallback we rather just produce a type-ID
*/
template<typename X>
struct _shall_forward { enum{ value = false };};
struct _allow_call { enum{ value = false };};
/* the following definitions enable some primitive types
* to be handed over to the boost::format implementation */
template<> struct _allow_call<string> { enum{ value = true }; };
template<> struct _allow_call<char> { enum{ value = true }; };
template<> struct _allow_call<uchar> { enum{ value = true }; };
template<> struct _allow_call<int> { enum{ value = true }; };
template<> struct _allow_call<uint> { enum{ value = true }; };
template<> struct _allow_call<short> { enum{ value = true }; };
template<> struct _allow_call<ushort> { enum{ value = true }; };
template<> struct _allow_call<int64_t> { enum{ value = true }; };
template<> struct _allow_call<uint64_t>{ enum{ value = true }; };
template<> struct _allow_call<float> { enum{ value = true }; };
template<> struct _allow_call<double> { enum{ value = true }; };
template<> struct _allow_call<void*> { enum{ value = true }; };
template<typename X>
struct _shall_format_directly
{
typedef typename lib::meta::UnConst<X>::Type BaseType;
enum{ value = _allow_call<BaseType>::value };
};
template<typename X>
struct _shall_format_directly<X*>
: _shall_format_directly<X>
{ };
/* the following definitions enable some basic types
* to be forwarded to boost::format literally */
template<> struct _shall_forward<string> { enum{ value = true }; };
template<> struct _shall_forward<char> { enum{ value = true }; };
template<> struct _shall_forward<uchar> { enum{ value = true }; };
template<> struct _shall_forward<int> { enum{ value = true }; };
template<> struct _shall_forward<uint> { enum{ value = true }; };
template<> struct _shall_forward<short> { enum{ value = true }; };
template<> struct _shall_forward<ushort> { enum{ value = true }; };
template<> struct _shall_forward<int64_t> { enum{ value = true }; };
template<> struct _shall_forward<uint64_t>{ enum{ value = true }; };
template<> struct _shall_forward<float> { enum{ value = true }; };
template<> struct _shall_forward<double> { enum{ value = true }; };
template<> struct _shall_forward<void*> { enum{ value = true }; };
template<typename X>
struct _shall_convert_toString
{
enum{ value = ! _shall_forward<X>::value
&& lib::meta::can_convertToString<X>::value
&& !lib::meta::is_sameType<X,char*>::value
};
enum{ value = ! _shall_format_directly<X>::value
&& lib::meta::can_convertToString<X>::value
};
};
@ -230,7 +246,7 @@ namespace util {
template<typename VAL, class SEL>
struct _Fmt::Converter
{
static string
static const string
prepare (VAL const&)
{
return string("«")+typeid(VAL).name()+"»";
@ -241,7 +257,7 @@ namespace util {
template<typename VAL>
struct _Fmt::Converter<VAL, typename enable_if< _shall_convert_toString<VAL> >::type>
{
static string
static const string
prepare (VAL const& val)
try {
return string(val);
@ -259,7 +275,7 @@ namespace util {
/** some basic types are directly forwarded down to the implementation;
* @note this requires explicit specialisations in format-string.cpp */
template<typename VAL>
struct _Fmt::Converter<VAL, typename enable_if< _shall_forward<VAL> >::type>
struct _Fmt::Converter<VAL, typename enable_if< _shall_format_directly<VAL> >::type>
{
static VAL const&
prepare (VAL const& val)
@ -269,14 +285,11 @@ namespace util {
};
template<typename VAL>
struct _Fmt::Converter<VAL*, typename enable_if< _shall_forward<VAL> >::type>
void
_Fmt::pushParameter (VAL * pV) ///< treat as const
{
static const VAL *
prepare (const VAL * const pVal)
{
return pVal;
}
};
pushParameter ((const VAL*) pV);
}

View file

@ -87,6 +87,36 @@ namespace meta {
};
/** strip const from type: naive implementation */
template<typename T>
struct UnConst
{
typedef T Type;
};
template<typename T>
struct UnConst<const T>
{
typedef T Type;
};
template<typename T>
struct UnConst<const T *>
{
typedef T* Type;
};
template<typename T>
struct UnConst<T * const>
{
typedef T* Type;
};
template<typename T>
struct UnConst<const T * const>
{
typedef T* Type;
};
/** semi-automatic detection if an instantiation is possible.
* Requires help by the template to be tested, which needs to define
* a typedef member \c is_defined. The embedded metafunction Test can be used

View file

@ -279,7 +279,6 @@ namespace test {
uint64_t ull(ll); uint64_t * pull = &ull;
float f(12.34); float * pf = & f;
double d(-12.34); double * pd = & d;
char c(0x40); char * pc = & c;
uchar uc(0xff); uchar * puc = & uc;
string str("Lumiera"); string * pstr = &str;
@ -293,14 +292,18 @@ namespace test {
CHECK (_Fmt("%d") % ull == _Fmt("%d") % pull);
CHECK (_Fmt("%e") % f == _Fmt("%e") % pf);
CHECK (_Fmt("%e") % d == _Fmt("%e") % pd);
CHECK (_Fmt("%g") % c == _Fmt("%g") % pc);
CHECK (_Fmt("%g") % uc == _Fmt("%g") % puc);
CHECK (_Fmt("%s") % str == _Fmt("%s") % pstr);
char c('a');
char pc[2] = {'a', '\0'};
CHECK (_Fmt("%g") % c == _Fmt("%g") % pc);
Verbose v(42);
Verbose *pv = &v;
void *vv = pv;
CHECK (_Fmt("__%s__") % v == "__Number-042__");
cout << "yyy=" << string(_Fmt("__%s__") % pv) << endl;
CHECK (_Fmt("__%s__") % pv == "__Number-042__");
CHECK (_Fmt("__%s__") % vv != "__Number-042__");