formatting-utils(#985): provide some basics

No more fiddling with printf just to show a number reliably!

simple functions to pretty-print addresses,
doubles and floats (fixed-point, with rounding).

Also make all these basic formatting helpers noexcept
This commit is contained in:
Fischlurch 2016-01-06 04:04:56 +01:00
parent 1814b1fc69
commit 60a7e7acb2
3 changed files with 125 additions and 15 deletions

View file

@ -42,6 +42,7 @@
#include "lib/error.hpp"
#include "lib/format-obj.hpp"
//#include "lib/format-string.hpp"
#include "lib/unique-malloc-owner.hpp"
#include "lib/symbol.hpp"
@ -49,11 +50,26 @@
#include <cxxabi.h>
#endif
#include <iomanip>
#include <sstream>
#include <string>
//using util::_Fmt;
using std::string;
namespace { // hard-wired configuration for debugging output....
// precision for rendering of double values
const auto DIAGNOSTICS_DOUBLE_PRECISION = 8;
const auto DIAGNOSTICS_FLOAT_PRECISION = 5;
/** amount of hex digits required to represent an address on this plattform */
const auto PLATFORM_ADDRESS_HEX_DIGITS = sizeof(size_t) * 2;
}
namespace lib {
namespace meta {
@ -132,7 +148,12 @@ apologies for that."
return typeName;
}
}}
}}// namespace lib::meta
/* === formatting and pretty printing support uitls === */
namespace util {
@ -141,11 +162,59 @@ namespace util {
}//(End) implementation details
using std::ostringstream;
using std::hex;
using std::setw;
using std::right;
using std::setfill;
using std::noshowbase;
/**
* @return fixed point string representation, never empty
* @note we set an explicit precision, since this is a diagnostic facility
* @remarks typically do not want to see all digits, but, for test code,
* we do want a predictable string representation of simple fractional
* values like `0.1` (which can not be represented as binary floats)
*/
string
showDouble (double val) noexcept
try {
ostringstream buffer;
buffer.precision (DIAGNOSTICS_DOUBLE_PRECISION);
buffer << val;
return buffer.str();
}
catch(...)
{ return ""; }
string
showFloat (float val) noexcept
try {
std::ostringstream buffer;
buffer.precision (DIAGNOSTICS_FLOAT_PRECISION);
buffer << val;
return buffer.str();
}
catch(...)
{ return ""; }
string
showAddr (void *addr) noexcept
try {
std::ostringstream buffer;
buffer << hex
<< noshowbase
<< setw (PLATFORM_ADDRESS_HEX_DIGITS)
<< setfill('_')
<< right
<< addr;
return buffer.str();
}
catch(...)
{ return ""; }

View file

@ -68,11 +68,15 @@ namespace meta {
std::string humanReadableTypeID (lib::Literal);
}} // namespace lib::meta
}}// namespace lib::meta
namespace util {
std::string showDouble (double) noexcept;
std::string showFloat (float) noexcept;
std::string showAddr (void *addr) noexcept;
} // namespace util

View file

@ -204,16 +204,18 @@ namespace meta {
*/
template<typename TY>
inline std::string
typeStr (const TY* obj=nullptr)
{
auto mangledType = obj? typeid(obj).name()
: typeid(TY).name();
return humanReadableTypeID (mangledType);
}
typeStr (const TY* obj =nullptr) noexcept
try {
auto mangledType = obj? typeid(obj).name()
: typeid(TY).name();
return humanReadableTypeID (mangledType);
}
catch(...)
{ return ""; }
template<typename TY>
inline std::string
typeStr (TY const& ref)
typeStr (TY const& ref) noexcept
{
return typeStr (&ref);
}
@ -234,20 +236,55 @@ namespace meta {
template<typename X, typename COND =void>
struct CustomStringConv
{
static std::string invoke (X const& x) { return "«"+typeStr(x)+"»"; }
static std::string
invoke (X const& x) noexcept
try { return "«"+typeStr(x)+"»"; }
catch(...) { return ""; }
};
template<typename X>
struct CustomStringConv<X, enable_if<can_convertToString<X>> >
{
static std::string
invoke (X const& val)
invoke (X const& val) noexcept
try { return std::string(val); }
catch(...) { return ""; }
};
// NOTE: this is meant to be extensible;
// more specialisations are e.g. in format-obj.hpp
}}// namespace lib::meta
namespace util {
/** pretty-print a double in fixed-point format */
std::string showDouble (double) noexcept;
std::string showFloat (float) noexcept;
/** pretty-print an address as hex-string */
std::string showAddr (void *addr) noexcept;
template<typename X>
inline std::string
showAddr (const X& elm) noexcept
{
return showAddr(&elm);
}
/** diagnostics helper for explicitly indicating pointers */
template<typename X>
inline std::string
showPtr (X* ptr =nullptr)
{
return ptr? showAddr(ptr) + "" + lib::meta::CustomStringConv<X>::invoke(*ptr)
: "⟂ «" + typeStr(ptr) + "»";
}
}} // namespace lib::meta
#endif
}// namespace util
#endif /*LIB_META_UTIL_H*/