handling of ptrs, first attempt
This commit is contained in:
parent
35ed2dcf5c
commit
c8f46f47c9
4 changed files with 145 additions and 85 deletions
|
|
@ -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 * );
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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__");
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue