diff --git a/src/lib/format-string.cpp b/src/lib/format-string.cpp index 927200f30..562fe10d1 100644 --- a/src/lib/format-string.cpp +++ b/src/lib/format-string.cpp @@ -69,10 +69,11 @@ namespace util { return reinterpret_cast (*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(" + 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 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 void - _Fmt::pushParameter (const VAL * const pVal) + _Fmt::pushParameter (const VAL * pVal) { if (pVal) - pushParameter (*pVal); + doFormatParameter (formatter_, *pVal); else - pushParameter (string("")); + doFormatParameter (formatter_, ""); } 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 * ); diff --git a/src/lib/format-string.hpp b/src/lib/format-string.hpp index af58a9bda..2e7f63060 100644 --- a/src/lib/format-string.hpp +++ b/src/lib/format-string.hpp @@ -99,10 +99,13 @@ namespace util { struct Converter; template - void pushParameter (VAL const&); + void pushParameter (const VAL); template - void pushParameter (const VAL * const); + void pushParameter (const VAL *); + + template + void pushParameter (VAL *); public: @@ -169,31 +172,44 @@ namespace util { * As fallback we rather just produce a type-ID */ template - 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 { enum{ value = true }; }; + template<> struct _allow_call { enum{ value = true }; }; + template<> struct _allow_call { enum{ value = true }; }; + template<> struct _allow_call { enum{ value = true }; }; + template<> struct _allow_call { enum{ value = true }; }; + template<> struct _allow_call { enum{ value = true }; }; + template<> struct _allow_call { enum{ value = true }; }; + template<> struct _allow_call { enum{ value = true }; }; + template<> struct _allow_call{ enum{ value = true }; }; + template<> struct _allow_call { enum{ value = true }; }; + template<> struct _allow_call { enum{ value = true }; }; + template<> struct _allow_call { enum{ value = true }; }; + + template + struct _shall_format_directly + { + typedef typename lib::meta::UnConst::Type BaseType; + + enum{ value = _allow_call::value }; + }; + + template + struct _shall_format_directly + : _shall_format_directly + { }; - /* the following definitions enable some basic types - * to be forwarded to boost::format literally */ - template<> struct _shall_forward { enum{ value = true }; }; - template<> struct _shall_forward { enum{ value = true }; }; - template<> struct _shall_forward { enum{ value = true }; }; - template<> struct _shall_forward { enum{ value = true }; }; - template<> struct _shall_forward { enum{ value = true }; }; - template<> struct _shall_forward { enum{ value = true }; }; - template<> struct _shall_forward { enum{ value = true }; }; - template<> struct _shall_forward { enum{ value = true }; }; - template<> struct _shall_forward{ enum{ value = true }; }; - template<> struct _shall_forward { enum{ value = true }; }; - template<> struct _shall_forward { enum{ value = true }; }; - template<> struct _shall_forward { enum{ value = true }; }; template struct _shall_convert_toString { - enum{ value = ! _shall_forward::value - && lib::meta::can_convertToString::value - && !lib::meta::is_sameType::value - }; + enum{ value = ! _shall_format_directly::value + && lib::meta::can_convertToString::value + }; }; @@ -230,7 +246,7 @@ namespace util { template struct _Fmt::Converter { - static string + static const string prepare (VAL const&) { return string("«")+typeid(VAL).name()+"»"; @@ -241,7 +257,7 @@ namespace util { template struct _Fmt::Converter >::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 - struct _Fmt::Converter >::type> + struct _Fmt::Converter >::type> { static VAL const& prepare (VAL const& val) @@ -269,14 +285,11 @@ namespace util { }; template - struct _Fmt::Converter >::type> + void + _Fmt::pushParameter (VAL * pV) ///< treat as const { - static const VAL * - prepare (const VAL * const pVal) - { - return pVal; - } - }; + pushParameter ((const VAL*) pV); + } diff --git a/src/lib/meta/util.hpp b/src/lib/meta/util.hpp index 91724943f..67dacc400 100644 --- a/src/lib/meta/util.hpp +++ b/src/lib/meta/util.hpp @@ -87,6 +87,36 @@ namespace meta { }; + /** strip const from type: naive implementation */ + template + struct UnConst + { + typedef T Type; + }; + + template + struct UnConst + { + typedef T Type; + }; + template + struct UnConst + { + typedef T* Type; + }; + template + struct UnConst + { + typedef T* Type; + }; + template + struct UnConst + { + 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 diff --git a/tests/lib/format-string-test.cpp b/tests/lib/format-string-test.cpp index 46cae95c1..6ba3b4c32 100644 --- a/tests/lib/format-string-test.cpp +++ b/tests/lib/format-string-test.cpp @@ -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__");